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

Commit 0c16dbe6 authored by Pawin Vongmasa's avatar Pawin Vongmasa
Browse files

RESTRICT AUTOMERGE mediaswcodec: Set "default" as preferred service

Usage mapper will be retrieved from the preferred service if system
properties for mediaswcodec's ION usage are not set.

Test: Define system property "ro.com.android.media.swcodec.ion.heapmask"
and check the log during the startup of mediaswcodec.

Test: Manually log the mapper activity; test if gets invoked from
mediaswcodec and CCodec.

Test: atest CtsMediaTestCases -- \
--module-arg CtsMediaTestCases:size:small

Bug: 144995284
Change-Id: Iebcd89bfa38de3c10b79f878462ba2af347ad332
parent 826e5c01
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@ cc_library_shared {
        "libbase",
        "libbase",
        "libcodec2_hidl@1.0",
        "libcodec2_hidl@1.0",
        "libcodec2_vndk",
        "libcodec2_vndk",
        "libhidlbase",
        "libutils",
        "libutils",
    ],
    ],


+394 −4
Original line number Original line Diff line number Diff line
@@ -18,21 +18,411 @@
#define LOG_TAG "CodecServiceRegistrant"
#define LOG_TAG "CodecServiceRegistrant"


#include <android-base/logging.h>
#include <android-base/logging.h>
#include <android-base/properties.h>


#include <C2Component.h>
#include <C2PlatformSupport.h>
#include <C2PlatformSupport.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/Configurable.h>
#include <codec2/hidl/1.0/types.h>
#include <hidl/HidlSupport.h>
#include <media/CodecServiceRegistrant.h>
#include <media/CodecServiceRegistrant.h>


extern "C" void RegisterCodecServices() {
namespace /* unnamed */ {

using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
using namespace ::android::hardware::media::c2::V1_0;
using namespace ::android::hardware::media::c2::V1_0;
using namespace ::android::hardware::media::c2::V1_0::utils;

constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;

// Converter from IComponentStore to C2ComponentStore.
class H2C2ComponentStore : public C2ComponentStore {
protected:
    sp<IComponentStore> mStore;
    sp<IConfigurable> mConfigurable;
public:
    explicit H2C2ComponentStore(sp<IComponentStore> const& store)
          : mStore{store},
            mConfigurable{[store]() -> sp<IConfigurable>{
                if (!store) {
                    return nullptr;
                }
                Return<sp<IConfigurable>> transResult =
                    store->getConfigurable();
                return transResult.isOk() ?
                        static_cast<sp<IConfigurable>>(transResult) :
                        nullptr;
            }()} {
        if (!mConfigurable) {
            LOG(ERROR) << "Preferred store is corrupted.";
        }
    }

    virtual ~H2C2ComponentStore() override = default;

    virtual c2_status_t config_sm(
            std::vector<C2Param*> const &params,
            std::vector<std::unique_ptr<C2SettingResult>>* const failures
            ) override {
        Params hidlParams;
        if (!createParamsBlob(&hidlParams, params)) {
            LOG(ERROR) << "config -- bad input.";
            return C2_TRANSACTION_FAILED;
        }
        c2_status_t status{};
        Return<void> transResult = mConfigurable->config(
                hidlParams,
                true,
                [&status, &params, failures](
                        Status s,
                        const hidl_vec<SettingResult> f,
                        const Params& o) {
                    status = static_cast<c2_status_t>(s);
                    if (status != C2_OK && status != C2_BAD_INDEX) {
                        LOG(DEBUG) << "config -- call failed: "
                                   << status << ".";
                    }
                    size_t i = failures->size();
                    failures->resize(i + f.size());
                    for (const SettingResult& sf : f) {
                        if (!objcpy(&(*failures)[i++], sf)) {
                            LOG(ERROR) << "config -- "
                                       << "invalid SettingResult returned.";
                            return;
                        }
                    }
                    if (!updateParamsFromBlob(params, o)) {
                        LOG(ERROR) << "config -- "
                                   << "failed to parse returned params.";
                        status = C2_CORRUPTED;
                    }
                });
        if (!transResult.isOk()) {
            LOG(ERROR) << "config -- transaction failed.";
            return C2_TRANSACTION_FAILED;
        }
        return status;
    };

    virtual c2_status_t copyBuffer(
            std::shared_ptr<C2GraphicBuffer>,
            std::shared_ptr<C2GraphicBuffer>) override {
        LOG(ERROR) << "copyBuffer -- not supported.";
        return C2_OMITTED;
    }

    virtual c2_status_t createComponent(
            C2String, std::shared_ptr<C2Component> *const component) override {
        component->reset();
        LOG(ERROR) << "createComponent -- not supported.";
        return C2_OMITTED;
    }

    virtual c2_status_t createInterface(
            C2String, std::shared_ptr<C2ComponentInterface> *const interface) {
        interface->reset();
        LOG(ERROR) << "createInterface -- not supported.";
        return C2_OMITTED;
    }

    virtual c2_status_t query_sm(
            const std::vector<C2Param *> &stackParams,
            const std::vector<C2Param::Index> &heapParamIndices,
            std::vector<std::unique_ptr<C2Param>> *const heapParams) const
            override {
        hidl_vec<ParamIndex> indices(
                stackParams.size() + heapParamIndices.size());
        size_t numIndices = 0;
        for (C2Param* const& stackParam : stackParams) {
            if (!stackParam) {
                LOG(WARNING) << "query -- null stack param encountered.";
                continue;
            }
            indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
        }
        size_t numStackIndices = numIndices;
        for (const C2Param::Index& index : heapParamIndices) {
            indices[numIndices++] =
                    static_cast<ParamIndex>(static_cast<uint32_t>(index));
        }
        indices.resize(numIndices);
        if (heapParams) {
            heapParams->reserve(heapParams->size() + numIndices);
        }
        c2_status_t status;
        Return<void> transResult = mConfigurable->query(
                indices,
                true,
                [&status, &numStackIndices, &stackParams, heapParams](
                        Status s, const Params& p) {
                    status = static_cast<c2_status_t>(s);
                    if (status != C2_OK && status != C2_BAD_INDEX) {
                        LOG(DEBUG) << "query -- call failed: "
                                   << status << ".";
                        return;
                    }
                    std::vector<C2Param*> paramPointers;
                    if (!parseParamsBlob(&paramPointers, p)) {
                        LOG(ERROR) << "query -- error while parsing params.";
                        status = C2_CORRUPTED;
                        return;
                    }
                    size_t i = 0;
                    for (auto it = paramPointers.begin();
                            it != paramPointers.end(); ) {
                        C2Param* paramPointer = *it;
                        if (numStackIndices > 0) {
                            --numStackIndices;
                            if (!paramPointer) {
                                LOG(WARNING) << "query -- null stack param.";
                                ++it;
                                continue;
                            }
                            for (; i < stackParams.size() && !stackParams[i]; ) {
                                ++i;
                            }
                            if (i >= stackParams.size()) {
                                LOG(ERROR) << "query -- unexpected error.";
                                status = C2_CORRUPTED;
                                return;
                            }
                            if (stackParams[i]->index() != paramPointer->index()) {
                                LOG(WARNING) << "query -- param skipped: "
                                                "index = "
                                             << stackParams[i]->index() << ".";
                                stackParams[i++]->invalidate();
                                continue;
                            }
                            if (!stackParams[i++]->updateFrom(*paramPointer)) {
                                LOG(WARNING) << "query -- param update failed: "
                                                "index = "
                                             << paramPointer->index() << ".";
                            }
                        } else {
                            if (!paramPointer) {
                                LOG(WARNING) << "query -- null heap param.";
                                ++it;
                                continue;
                            }
                            if (!heapParams) {
                                LOG(WARNING) << "query -- "
                                                "unexpected extra stack param.";
                            } else {
                                heapParams->emplace_back(
                                        C2Param::Copy(*paramPointer));
                            }
                        }
                        ++it;
                    }
                });
        if (!transResult.isOk()) {
            LOG(ERROR) << "query -- transaction failed.";
            return C2_TRANSACTION_FAILED;
        }
        return status;
    }

    virtual c2_status_t querySupportedParams_nb(
            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
        c2_status_t status;
        Return<void> transResult = mConfigurable->querySupportedParams(
                std::numeric_limits<uint32_t>::min(),
                std::numeric_limits<uint32_t>::max(),
                [&status, params](
                        Status s,
                        const hidl_vec<ParamDescriptor>& p) {
                    status = static_cast<c2_status_t>(s);
                    if (status != C2_OK) {
                        LOG(DEBUG) << "querySupportedParams -- call failed: "
                                   << status << ".";
                        return;
                    }
                    size_t i = params->size();
                    params->resize(i + p.size());
                    for (const ParamDescriptor& sp : p) {
                        if (!objcpy(&(*params)[i++], sp)) {
                            LOG(ERROR) << "querySupportedParams -- "
                                       << "invalid returned ParamDescriptor.";
                            return;
                        }
                    }
                });
        if (!transResult.isOk()) {
            LOG(ERROR) << "querySupportedParams -- transaction failed.";
            return C2_TRANSACTION_FAILED;
        }
        return status;
    }

    virtual c2_status_t querySupportedValues_sm(
            std::vector<C2FieldSupportedValuesQuery> &fields) const {
        hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
        for (size_t i = 0; i < fields.size(); ++i) {
            if (!objcpy(&inFields[i], fields[i])) {
                LOG(ERROR) << "querySupportedValues -- bad input";
                return C2_TRANSACTION_FAILED;
            }
        }

        c2_status_t status;
        Return<void> transResult = mConfigurable->querySupportedValues(
                inFields,
                true,
                [&status, &inFields, &fields](
                        Status s,
                        const hidl_vec<FieldSupportedValuesQueryResult>& r) {
                    status = static_cast<c2_status_t>(s);
                    if (status != C2_OK) {
                        LOG(DEBUG) << "querySupportedValues -- call failed: "
                                   << status << ".";
                        return;
                    }
                    if (r.size() != fields.size()) {
                        LOG(ERROR) << "querySupportedValues -- "
                                      "input and output lists "
                                      "have different sizes.";
                        status = C2_CORRUPTED;
                        return;
                    }
                    for (size_t i = 0; i < fields.size(); ++i) {
                        if (!objcpy(&fields[i], inFields[i], r[i])) {
                            LOG(ERROR) << "querySupportedValues -- "
                                          "invalid returned value.";
                            status = C2_CORRUPTED;
                            return;
                        }
                    }
                });
        if (!transResult.isOk()) {
            LOG(ERROR) << "querySupportedValues -- transaction failed.";
            return C2_TRANSACTION_FAILED;
        }
        return status;
    }

    virtual C2String getName() const {
        C2String outName;
        Return<void> transResult = mConfigurable->getName(
                [&outName](const hidl_string& name) {
                    outName = name.c_str();
                });
        if (!transResult.isOk()) {
            LOG(ERROR) << "getName -- transaction failed.";
        }
        return outName;
    }

    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const
            override {
        struct SimpleParamReflector : public C2ParamReflector {
            virtual std::unique_ptr<C2StructDescriptor> describe(
                    C2Param::CoreIndex coreIndex) const {
                hidl_vec<ParamIndex> indices(1);
                indices[0] = static_cast<ParamIndex>(coreIndex.coreIndex());
                std::unique_ptr<C2StructDescriptor> descriptor;
                Return<void> transResult = mBase->getStructDescriptors(
                        indices,
                        [&descriptor](
                                Status s,
                                const hidl_vec<StructDescriptor>& sd) {
                            c2_status_t status = static_cast<c2_status_t>(s);
                            if (status != C2_OK) {
                                LOG(DEBUG) << "SimpleParamReflector -- "
                                              "getStructDescriptors() failed: "
                                           << status << ".";
                                descriptor.reset();
                                return;
                            }
                            if (sd.size() != 1) {
                                LOG(DEBUG) << "SimpleParamReflector -- "
                                              "getStructDescriptors() "
                                              "returned vector of size "
                                           << sd.size() << ". "
                                              "It should be 1.";
                                descriptor.reset();
                                return;
                            }
                            if (!objcpy(&descriptor, sd[0])) {
                                LOG(DEBUG) << "SimpleParamReflector -- "
                                              "getStructDescriptors() returned "
                                              "corrupted data.";
                                descriptor.reset();
                                return;
                            }
                        });
                return descriptor;
            }

            explicit SimpleParamReflector(sp<IComponentStore> base)
                : mBase(base) { }

            sp<IComponentStore> mBase;
        };

        return std::make_shared<SimpleParamReflector>(mStore);
    }

    virtual std::vector<std::shared_ptr<const C2Component::Traits>>
            listComponents() override {
        LOG(ERROR) << "listComponents -- not supported.";
        return {};
    }
};

bool ionPropertiesDefined() {
    using namespace ::android::base;
    std::string heapMask =
        GetProperty("ro.com.android.media.swcodec.ion.heapmask", "undefined");
    std::string flags =
        GetProperty("ro.com.android.media.swcodec.ion.flags", "undefined");
    std::string align =
        GetProperty("ro.com.android.media.swcodec.ion.align", "undefined");
    if (heapMask != "undefined" ||
            flags != "undefined" ||
            align != "undefined") {
        LOG(INFO)
                << "Some system properties for mediaswcodec ION usage are set: "
                << "heapmask = " << heapMask << ", "
                << "flags = " << flags << ", "
                << "align = " << align << ". "
                << "Preferred Codec2 store is defaulted to \"software\".";
        return true;
    }
    return false;
}

} // unnamed namespace

extern "C" void RegisterCodecServices() {
    using ComponentStore = ::android::hardware::media::c2::V1_0::utils::
            ComponentStore;
    LOG(INFO) << "Creating software Codec2 service...";
    LOG(INFO) << "Creating software Codec2 service...";
    android::sp<IComponentStore> store =
    sp<ComponentStore> store =
        new utils::ComponentStore(
        new ComponentStore(::android::GetCodec2PlatformComponentStore());
                android::GetCodec2PlatformComponentStore());
    if (store == nullptr) {
    if (store == nullptr) {
        LOG(ERROR) <<
        LOG(ERROR) <<
                "Cannot create software Codec2 service.";
                "Cannot create software Codec2 service.";
    } else {
    } else {
        if (!ionPropertiesDefined()) {
            std::string preferredStoreName = "default";
            sp<IComponentStore> preferredStore =
                IComponentStore::getService(preferredStoreName.c_str());
            if (preferredStore) {
                ::android::SetPreferredCodec2ComponentStore(
                        std::make_shared<H2C2ComponentStore>(preferredStore));
                LOG(INFO) <<
                        "Preferred Codec2 store is set to \"" <<
                        preferredStoreName << "\".";
            } else {
                LOG(INFO) <<
                        "Preferred Codec2 store is defaulted to \"software\".";
            }
        }
        if (store->registerAsService("software") != android::OK) {
        if (store->registerAsService("software") != android::OK) {
            LOG(ERROR) <<
            LOG(ERROR) <<
                    "Cannot register software Codec2 service.";
                    "Cannot register software Codec2 service.";