blob: 972e64b09e97165451e2a037b51e9fe4d15b6c33 [file] [log] [blame]
/*
* 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 <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <utils/Errors.h>
#include <system/audio_effect.h>
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(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(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 <typename T>
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 <typename T>
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();
}
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 <typename T>
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 <typename T>
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; }
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