Make change and version bump to r_aml_300801400 for mainline module file: apex/manifest_codec.json

Change-Id: I1df760de5013795cb95a1e7b74a90276854d5100
diff --git a/apex/manifest.json b/apex/manifest.json
index 4a874d1..a3684cf 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media",
-  "version": 300801300
+  "version": 300801400
 }
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 1189cdb..faf529f 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.media.swcodec",
-  "version": 300801300
+  "version": 300801400
 }
diff --git a/media/codec2/components/base/SimpleC2Interface.cpp b/media/codec2/components/base/SimpleC2Interface.cpp
index 5c019f3..29740d1 100644
--- a/media/codec2/components/base/SimpleC2Interface.cpp
+++ b/media/codec2/components/base/SimpleC2Interface.cpp
@@ -39,6 +39,16 @@
     setDerivedInstance(this);
 
     addParameter(
+            DefineParam(mApiFeatures, C2_PARAMKEY_API_FEATURES)
+            .withConstValue(new C2ApiFeaturesSetting(C2Config::api_feature_t(
+                    API_REFLECTION |
+                    API_VALUES |
+                    API_CURRENT_VALUES |
+                    API_DEPENDENCY |
+                    API_SAME_INPUT_BUFFER)))
+            .build());
+
+    addParameter(
             DefineParam(mName, C2_PARAMKEY_COMPONENT_NAME)
             .withConstValue(AllocSharedString<C2ComponentNameSetting>(name.c_str()))
             .build());
@@ -305,7 +315,6 @@
     Clients need to handle the following base params due to custom dependency.
 
     std::shared_ptr<C2ApiLevelSetting> mApiLevel;
-    std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures;
     std::shared_ptr<C2ComponentAttributesSetting> mAttrib;
 
     std::shared_ptr<C2PortSuggestedBufferCountTuning::input> mSuggestedInputBufferCount;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 74e105e..7e9090f 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -460,8 +460,8 @@
 
     const C2ConstGraphicBlock inBuffer =
         inputBuffer->data().graphicBlocks().front();
-    if (inBuffer.width() != mSize->width ||
-        inBuffer.height() != mSize->height) {
+    if (inBuffer.width() < mSize->width ||
+        inBuffer.height() < mSize->height) {
         ALOGE("unexpected Input buffer attributes %d(%d) x %d(%d)",
               inBuffer.width(), mSize->width, inBuffer.height(),
               mSize->height);
@@ -472,8 +472,8 @@
     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
     vpx_image_t raw_frame;
     const C2PlanarLayout &layout = rView->layout();
-    uint32_t width = rView->width();
-    uint32_t height = rView->height();
+    uint32_t width = mSize->width;
+    uint32_t height = mSize->height;
     if (width > 0x8000 || height > 0x8000) {
         ALOGE("Image too big: %u x %u", width, height);
         work->result = C2_BAD_VALUE;
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index a3fff35..6f8b1d4 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1955,11 +1955,98 @@
             inputSurface->getHalInterface()));
 }
 
-static void MaybeLogUnrecognizedName(const char *func, const std::string &name) {
-    thread_local std::set<std::string> sLogged{};
-    if (sLogged.insert(name).second) {
-        ALOGW("%s: Unrecognized interface name: %s", func, name.c_str());
+class IntfCache {
+public:
+    IntfCache() = default;
+
+    status_t init(const std::string &name) {
+        std::shared_ptr<Codec2Client::Interface> intf{
+            Codec2Client::CreateInterfaceByName(name.c_str())};
+        if (!intf) {
+            ALOGW("IntfCache [%s]: Unrecognized interface name", name.c_str());
+            mInitStatus = NO_INIT;
+            return NO_INIT;
+        }
+        const static C2StreamUsageTuning::input sUsage{0u /* stream id */};
+        mFields.push_back(C2FieldSupportedValuesQuery::Possible(
+                C2ParamField{&sUsage, &sUsage.value}));
+        c2_status_t err = intf->querySupportedValues(mFields, C2_MAY_BLOCK);
+        if (err != C2_OK) {
+            ALOGW("IntfCache [%s]: failed to query usage supported value (err=%d)",
+                    name.c_str(), err);
+            mFields[0].status = err;
+        }
+        std::vector<std::unique_ptr<C2Param>> params;
+        err = intf->query(
+                {&mApiFeatures},
+                {C2PortAllocatorsTuning::input::PARAM_TYPE},
+                C2_MAY_BLOCK,
+                &params);
+        if (err != C2_OK && err != C2_BAD_INDEX) {
+            ALOGW("IntfCache [%s]: failed to query api features (err=%d)",
+                    name.c_str(), err);
+        }
+        while (!params.empty()) {
+            C2Param *param = params.back().release();
+            params.pop_back();
+            if (!param) {
+                continue;
+            }
+            if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
+                mInputAllocators.reset(
+                        C2PortAllocatorsTuning::input::From(params[0].get()));
+            }
+        }
+        mInitStatus = OK;
+        return OK;
     }
+
+    status_t initCheck() const { return mInitStatus; }
+
+    const C2FieldSupportedValuesQuery &getUsageSupportedValues() const {
+        CHECK_EQ(1u, mFields.size());
+        return mFields[0];
+    }
+
+    const C2ApiFeaturesSetting &getApiFeatures() const {
+        return mApiFeatures;
+    }
+
+    const C2PortAllocatorsTuning::input &getInputAllocators() const {
+        static std::unique_ptr<C2PortAllocatorsTuning::input> sInvalidated = []{
+            std::unique_ptr<C2PortAllocatorsTuning::input> param =
+                C2PortAllocatorsTuning::input::AllocUnique(0);
+            param->invalidate();
+            return param;
+        }();
+        return mInputAllocators ? *mInputAllocators : *sInvalidated;
+    }
+
+private:
+    status_t mInitStatus{NO_INIT};
+
+    std::vector<C2FieldSupportedValuesQuery> mFields;
+    C2ApiFeaturesSetting mApiFeatures;
+    std::unique_ptr<C2PortAllocatorsTuning::input> mInputAllocators;
+};
+
+static const IntfCache &GetIntfCache(const std::string &name) {
+    static IntfCache sNullIntfCache;
+    static std::mutex sMutex;
+    static std::map<std::string, IntfCache> sCache;
+    std::unique_lock<std::mutex> lock{sMutex};
+    auto it = sCache.find(name);
+    if (it == sCache.end()) {
+        lock.unlock();
+        IntfCache intfCache;
+        status_t err = intfCache.init(name);
+        if (err != OK) {
+            return sNullIntfCache;
+        }
+        lock.lock();
+        it = sCache.insert({name, std::move(intfCache)}).first;
+    }
+    return it->second;
 }
 
 static status_t GetCommonAllocatorIds(
@@ -1977,24 +2064,16 @@
     }
     bool firstIteration = true;
     for (const std::string &name : names) {
-        std::shared_ptr<Codec2Client::Interface> intf{
-            Codec2Client::CreateInterfaceByName(name.c_str())};
-        if (!intf) {
-            MaybeLogUnrecognizedName(__FUNCTION__, name);
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
             continue;
         }
-        std::vector<std::unique_ptr<C2Param>> params;
-        c2_status_t err = intf->query(
-                {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, &params);
+        const C2PortAllocatorsTuning::input &allocators = intfCache.getInputAllocators();
         if (firstIteration) {
             firstIteration = false;
-            if (err == C2_OK && params.size() == 1u) {
-                C2PortAllocatorsTuning::input *allocators =
-                    C2PortAllocatorsTuning::input::From(params[0].get());
-                if (allocators && allocators->flexCount() > 0) {
-                    ids->insert(allocators->m.values,
-                                allocators->m.values + allocators->flexCount());
-                }
+            if (allocators && allocators.flexCount() > 0) {
+                ids->insert(allocators.m.values,
+                            allocators.m.values + allocators.flexCount());
             }
             if (ids->empty()) {
                 // The component does not advertise allocators. Use default.
@@ -2003,24 +2082,20 @@
             continue;
         }
         bool filtered = false;
-        if (err == C2_OK && params.size() == 1u) {
-            C2PortAllocatorsTuning::input *allocators =
-                C2PortAllocatorsTuning::input::From(params[0].get());
-            if (allocators && allocators->flexCount() > 0) {
-                filtered = true;
-                for (auto it = ids->begin(); it != ids->end(); ) {
-                    bool found = false;
-                    for (size_t j = 0; j < allocators->flexCount(); ++j) {
-                        if (allocators->m.values[j] == *it) {
-                            found = true;
-                            break;
-                        }
+        if (allocators && allocators.flexCount() > 0) {
+            filtered = true;
+            for (auto it = ids->begin(); it != ids->end(); ) {
+                bool found = false;
+                for (size_t j = 0; j < allocators.flexCount(); ++j) {
+                    if (allocators.m.values[j] == *it) {
+                        found = true;
+                        break;
                     }
-                    if (found) {
-                        ++it;
-                    } else {
-                        it = ids->erase(it);
-                    }
+                }
+                if (found) {
+                    ++it;
+                } else {
+                    it = ids->erase(it);
                 }
             }
         }
@@ -2052,23 +2127,16 @@
     *minUsage = 0;
     *maxUsage = ~0ull;
     for (const std::string &name : names) {
-        std::shared_ptr<Codec2Client::Interface> intf{
-            Codec2Client::CreateInterfaceByName(name.c_str())};
-        if (!intf) {
-            MaybeLogUnrecognizedName(__FUNCTION__, name);
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
             continue;
         }
-        std::vector<C2FieldSupportedValuesQuery> fields;
-        fields.push_back(C2FieldSupportedValuesQuery::Possible(
-                C2ParamField{&sUsage, &sUsage.value}));
-        c2_status_t err = intf->querySupportedValues(fields, C2_MAY_BLOCK);
-        if (err != C2_OK) {
+        const C2FieldSupportedValuesQuery &usageSupportedValues =
+            intfCache.getUsageSupportedValues();
+        if (usageSupportedValues.status != C2_OK) {
             continue;
         }
-        if (fields[0].status != C2_OK) {
-            continue;
-        }
-        const C2FieldSupportedValues &supported = fields[0].values;
+        const C2FieldSupportedValues &supported = usageSupportedValues.values;
         if (supported.type != C2FieldSupportedValues::FLAGS) {
             continue;
         }
@@ -2089,6 +2157,17 @@
 // static
 status_t CCodec::CanFetchLinearBlock(
         const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible) {
+    for (const std::string &name : names) {
+        const IntfCache &intfCache = GetIntfCache(name);
+        if (intfCache.initCheck() != OK) {
+            continue;
+        }
+        const C2ApiFeaturesSetting &features = intfCache.getApiFeatures();
+        if (features && !(features.value & API_SAME_INPUT_BUFFER)) {
+            *isCompatible = false;
+            return OK;
+        }
+    }
     uint64_t minUsage = usage.expected;
     uint64_t maxUsage = ~0ull;
     std::set<C2Allocator::id_t> allocators;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 4345a9f..c07f3dc 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -916,6 +916,12 @@
 
     if (inputFormat != nullptr) {
         bool graphic = (iStreamFormat.value == C2BufferData::GRAPHIC);
+        C2Config::api_feature_t apiFeatures = C2Config::api_feature_t(
+                API_REFLECTION |
+                API_VALUES |
+                API_CURRENT_VALUES |
+                API_DEPENDENCY |
+                API_SAME_INPUT_BUFFER);
         std::shared_ptr<C2BlockPool> pool;
         {
             Mutexed<BlockPools>::Locked pools(mBlockPools);
@@ -927,14 +933,15 @@
             // query C2PortAllocatorsTuning::input from component. If an allocator ID is obtained
             // from component, create the input block pool with given ID. Otherwise, use default IDs.
             std::vector<std::unique_ptr<C2Param>> params;
-            err = mComponent->query({ },
+            C2ApiFeaturesSetting featuresSetting{apiFeatures};
+            err = mComponent->query({ &featuresSetting },
                                     { C2PortAllocatorsTuning::input::PARAM_TYPE },
                                     C2_DONT_BLOCK,
                                     &params);
             if ((err != C2_OK && err != C2_BAD_INDEX) || params.size() != 1) {
                 ALOGD("[%s] Query input allocators returned %zu params => %s (%u)",
                         mName, params.size(), asString(err), err);
-            } else if (err == C2_OK && params.size() == 1) {
+            } else if (params.size() == 1) {
                 C2PortAllocatorsTuning::input *inputAllocators =
                     C2PortAllocatorsTuning::input::From(params[0].get());
                 if (inputAllocators && inputAllocators->flexCount() > 0) {
@@ -949,6 +956,9 @@
                     }
                 }
             }
+            if (featuresSetting) {
+                apiFeatures = featuresSetting.value;
+            }
 
             // TODO: use C2Component wrapper to associate this pool with ourselves
             if ((poolMask >> pools->inputAllocatorId) & 1) {
@@ -982,7 +992,10 @@
         input->numSlots = numInputSlots;
         input->extraBuffers.flush();
         input->numExtraSlots = 0u;
-        if (!buffersBoundToCodec) {
+        bool conforming = (apiFeatures & API_SAME_INPUT_BUFFER);
+        // For encrypted content, framework decrypts source buffer (ashmem) into
+        // C2Buffers. Thus non-conforming codecs can process these.
+        if (!buffersBoundToCodec && (hasCryptoOrDescrambler() || conforming)) {
             input->buffers.reset(new SlotInputBuffers(mName));
         } else if (graphic) {
             if (mInputSurface) {