/* * Copyright (C) 2023 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. */ #pragma once #include #include #include #include #include #include #include #include #include namespace android { namespace effect { namespace utils { /** * A wrapper class of legacy effect_param_t to avoid raw pointer read/write everywhere. * The wrapper use the reference of underlying effect_param_t structure, and does not manage * ownership of the structure. * Thread safety is not in consideration in this class for now. */ class EffectParamWrapper { public: explicit EffectParamWrapper(const effect_param_t& param) : mParam(param) {} // validate command size to be at least parameterSize + valueSize after effect_param_t bool validateCmdSize(size_t cmdSize) const { return (uint64_t)getPaddedParameterSize() + mParam.vsize + sizeof(effect_param_t) <= cmdSize; } /** * validate parameter and value size to be at least equals to the target size. */ bool validateParamValueSize(size_t paramSize, size_t valueSize) const { return mParam.psize >= paramSize && mParam.vsize >= valueSize; } std::string toString() const { std::ostringstream os; os << "effect_param_t: { "; os << "status: " << mParam.status << ", p: " << mParam.psize << " (padded: " << getPaddedParameterSize() << "), v: " << mParam.vsize << ", dataAddr: " << &mParam.data; os << "}"; return os.str(); } status_t copyDataWithCheck(void* dst, const void* src, size_t len, size_t offset, size_t max) { if (!dst || !src || len + offset > max) { return BAD_VALUE; } std::memcpy(dst, src, len); return OK; } status_t readFromData(void* buf, size_t len, size_t offset, size_t max) { return copyDataWithCheck(buf, mParam.data + offset, len, offset, max); } status_t getStatus() const { return mParam.status; } size_t getPaddedParameterSize() const { return padding(mParam.psize); } size_t getParameterSize() const { return mParam.psize; } size_t getValueSize() const { return mParam.vsize; } const uint8_t* getValueAddress() const { return (uint8_t*)mParam.data + getPaddedParameterSize(); } uint64_t getTotalSize() const { return (uint64_t)sizeof(effect_param_t) + getPaddedParameterSize() + getValueSize(); } /** * Get reference to effect_param_t. */ const effect_param_t& getEffectParam() const { return mParam; } bool operator==(const EffectParamWrapper& other) const { return (&other == this) || 0 == std::memcmp(&mParam, &other.mParam, sizeof(effect_param_t)); } /** * Padding psize to 32 bits aligned, because "start of value field inside * the data field is always on a 32 bits boundary". */ static constexpr inline size_t padding(size_t size) { return ((size - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); } private: /* member with variable sized type at end of class */ const effect_param_t& mParam; }; /** * Reader class of effect_param_t data buffer. */ class EffectParamReader : public EffectParamWrapper { public: explicit EffectParamReader(const effect_param_t& param) : EffectParamWrapper(param), mValueROffset(getPaddedParameterSize()) {} /** * Read n value of type T from data to buf, mParamROffset will advance n * sizeof(T) if success, * no advance if failure. */ template status_t readFromParameter(T* buf, size_t n = 1) { size_t len = n * sizeof(T); status_t ret = readFromData(buf, len, mParamROffset /* param offset */, getParameterSize() /* max offset */); if (OK == ret) { mParamROffset += len; } return ret; } /** * Read number of value in type T from data to buf, mValueROffset will advance n * sizeof(T) if * success, no advance if failure. */ template status_t readFromValue(T* buf, size_t n = 1) { size_t len = n * sizeof(T); status_t ret = readFromData(buf, len, mValueROffset /* data offset */, getPaddedParameterSize() + getValueSize() /* max offset */); if (OK == ret) { mValueROffset += len; } return ret; } std::string toString() const { std::ostringstream os; os << EffectParamWrapper::toString(); os << ", paramROffset: " << mParamROffset; os << ", valueROffset: " << mValueROffset; return os.str(); } void reset() { mParamROffset = 0; mValueROffset = getPaddedParameterSize(); } private: size_t mParamROffset = 0; size_t mValueROffset = 0; }; /** * Writer class of effect_param_t data buffer. */ class EffectParamWriter : public EffectParamReader { public: explicit EffectParamWriter(effect_param_t& param) : EffectParamReader(param), mParam(param), mValueWOffset(getPaddedParameterSize()) { } /** * Write n number of param in type T from buf to data, mParamWOffset will advance n * sizeof(T) * if success, no advance if failure. */ template status_t writeToParameter(const T* buf, size_t n = 1) { size_t len = n * sizeof(T); status_t ret = writeToData(buf, len, mParamWOffset /* data offset */, getParameterSize() /* max */); if (OK == ret) { mParamWOffset += len; } return ret; } status_t writeToData(const void* buf, size_t len, size_t offset, size_t max) { return copyDataWithCheck(mParam.data + offset, buf, len, offset, max); } /** * Write n number of value in type T from buf to data, mValueWOffset will advance n * sizeof(T) * if success, no advance if failure. */ template status_t writeToValue(const T* buf, size_t n = 1) { size_t len = n * sizeof(T); status_t ret = writeToData(buf, len, mValueWOffset /* data offset */, getPaddedParameterSize() + getValueSize() /* max */); if (OK == ret) { mValueWOffset += len; } return ret; } /** * Set the current value write offset to vsize. * Together with getTotalSize(), can be used by getParameter to set replySize. */ void finishValueWrite() { mParam.vsize = mValueWOffset - getPaddedParameterSize(); } void setStatus(status_t status) { mParam.status = status; } /** * Overwrite the entire effect_param_t with input. */ status_t overwrite(const effect_param_t& param) { EffectParamReader reader(param); const auto size = reader.getTotalSize(); if (size > getTotalSize()) { return BAD_VALUE; } std::memcpy((void *)&mParam, (void *)&reader.getEffectParam(), size); reset(); mValueWOffset += reader.getValueSize(); return OK; } /** * Reset the offsets with underlying effect_param_t. */ void reset() { EffectParamReader::reset(); mParamWOffset = 0; mValueWOffset = getPaddedParameterSize(); } std::string toString() const { std::ostringstream os; os << EffectParamReader::toString(); os << ", paramWOffset: " << mParamWOffset; os << ", valueWOffset: " << mValueWOffset; return os.str(); } private: effect_param_t& mParam; size_t mParamWOffset = 0; size_t mValueWOffset = 0; }; } // namespace utils } // namespace effect } // namespace android