1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <algorithm> 20 #include <cstddef> 21 #include <cstdint> 22 #include <cstring> 23 #include <sstream> 24 #include <string> 25 #include <sys/types.h> 26 #include <utils/Errors.h> 27 28 #include <system/audio_effect.h> 29 30 namespace android { 31 namespace effect { 32 namespace utils { 33 34 /** 35 * A wrapper class of legacy effect_param_t to avoid raw pointer read/write everywhere. 36 * The wrapper use the reference of underlying effect_param_t structure, and does not manage 37 * ownership of the structure. 38 * Thread safety is not in consideration in this class for now. 39 */ 40 class EffectParamWrapper { 41 public: EffectParamWrapper(const effect_param_t & param)42 explicit EffectParamWrapper(const effect_param_t& param) : mParam(param) {} 43 44 // validate command size to be at least parameterSize + valueSize after effect_param_t validateCmdSize(size_t cmdSize)45 bool validateCmdSize(size_t cmdSize) const { 46 return (uint64_t)getPaddedParameterSize() + mParam.vsize + sizeof(effect_param_t) <= 47 cmdSize; 48 } 49 50 /** 51 * validate parameter and value size to be at least equals to the target size. 52 */ validateParamValueSize(size_t paramSize,size_t valueSize)53 bool validateParamValueSize(size_t paramSize, size_t valueSize) const { 54 return mParam.psize >= paramSize && mParam.vsize >= valueSize; 55 } 56 toString()57 std::string toString() const { 58 std::ostringstream os; 59 os << "effect_param_t: { "; 60 os << "status: " << mParam.status << ", p: " << mParam.psize 61 << " (padded: " << getPaddedParameterSize() << "), v: " << mParam.vsize 62 << ", dataAddr: " << &mParam.data; 63 os << "}"; 64 return os.str(); 65 } 66 copyDataWithCheck(void * dst,const void * src,size_t len,size_t offset,size_t max)67 status_t copyDataWithCheck(void* dst, const void* src, size_t len, 68 size_t offset, size_t max) { 69 if (!dst || !src || len + offset > max) { 70 return BAD_VALUE; 71 } 72 std::memcpy(dst, src, len); 73 return OK; 74 } 75 readFromData(void * buf,size_t len,size_t offset,size_t max)76 status_t readFromData(void* buf, size_t len, size_t offset, size_t max) { 77 return copyDataWithCheck(buf, mParam.data + offset, len, offset, max); 78 } 79 getStatus()80 status_t getStatus() const { return mParam.status; } getPaddedParameterSize()81 size_t getPaddedParameterSize() const { return padding(mParam.psize); } getParameterSize()82 size_t getParameterSize() const { return mParam.psize; } getValueSize()83 size_t getValueSize() const { return mParam.vsize; } getValueAddress()84 const uint8_t* getValueAddress() const { 85 return (uint8_t*)mParam.data + getPaddedParameterSize(); 86 } 87 getTotalSize()88 uint64_t getTotalSize() const { 89 return (uint64_t)sizeof(effect_param_t) + getPaddedParameterSize() + getValueSize(); 90 } 91 92 /** 93 * Get reference to effect_param_t. 94 */ getEffectParam()95 const effect_param_t& getEffectParam() const { return mParam; } 96 97 bool operator==(const EffectParamWrapper& other) const { 98 return (&other == this) || 0 == std::memcmp(&mParam, &other.mParam, sizeof(effect_param_t)); 99 } 100 101 /** 102 * Padding psize to 32 bits aligned, because "start of value field inside 103 * the data field is always on a 32 bits boundary". 104 */ padding(size_t size)105 static constexpr inline size_t padding(size_t size) { 106 return ((size - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 107 } 108 109 private: 110 /* member with variable sized type at end of class */ 111 const effect_param_t& mParam; 112 }; 113 114 /** 115 * Reader class of effect_param_t data buffer. 116 */ 117 class EffectParamReader : public EffectParamWrapper { 118 public: EffectParamReader(const effect_param_t & param)119 explicit EffectParamReader(const effect_param_t& param) 120 : EffectParamWrapper(param), mValueROffset(getPaddedParameterSize()) {} 121 122 /** 123 * Read n value of type T from data to buf, mParamROffset will advance n * sizeof(T) if success, 124 * no advance if failure. 125 */ 126 template <typename T> 127 status_t readFromParameter(T* buf, size_t n = 1) { 128 size_t len = n * sizeof(T); 129 status_t ret = readFromData(buf, len, mParamROffset /* param offset */, 130 getParameterSize() /* max offset */); 131 if (OK == ret) { 132 mParamROffset += len; 133 } 134 return ret; 135 } 136 137 /** 138 * Read number of value in type T from data to buf, mValueROffset will advance n * sizeof(T) if 139 * success, no advance if failure. 140 */ 141 template <typename T> 142 status_t readFromValue(T* buf, size_t n = 1) { 143 size_t len = n * sizeof(T); 144 status_t ret = readFromData(buf, len, mValueROffset /* data offset */, 145 getPaddedParameterSize() + getValueSize() /* max offset */); 146 if (OK == ret) { 147 mValueROffset += len; 148 } 149 return ret; 150 } 151 toString()152 std::string toString() const { 153 std::ostringstream os; 154 os << EffectParamWrapper::toString(); 155 os << ", paramROffset: " << mParamROffset; 156 os << ", valueROffset: " << mValueROffset; 157 return os.str(); 158 } 159 reset()160 void reset() { 161 mParamROffset = 0; 162 mValueROffset = getPaddedParameterSize(); 163 } 164 165 private: 166 size_t mParamROffset = 0; 167 size_t mValueROffset = 0; 168 }; 169 170 /** 171 * Writer class of effect_param_t data buffer. 172 */ 173 class EffectParamWriter : public EffectParamReader { 174 public: EffectParamWriter(effect_param_t & param)175 explicit EffectParamWriter(effect_param_t& param) 176 : EffectParamReader(param), mParam(param), mValueWOffset(getPaddedParameterSize()) { 177 } 178 179 /** 180 * Write n number of param in type T from buf to data, mParamWOffset will advance n * sizeof(T) 181 * if success, no advance if failure. 182 */ 183 template <typename T> 184 status_t writeToParameter(const T* buf, size_t n = 1) { 185 size_t len = n * sizeof(T); 186 status_t ret = writeToData(buf, len, mParamWOffset /* data offset */, 187 getParameterSize() /* max */); 188 if (OK == ret) { 189 mParamWOffset += len; 190 } 191 return ret; 192 } 193 writeToData(const void * buf,size_t len,size_t offset,size_t max)194 status_t writeToData(const void* buf, size_t len, size_t offset, size_t max) { 195 return copyDataWithCheck(mParam.data + offset, buf, len, offset, max); 196 } 197 /** 198 * Write n number of value in type T from buf to data, mValueWOffset will advance n * sizeof(T) 199 * if success, no advance if failure. 200 */ 201 template <typename T> 202 status_t writeToValue(const T* buf, size_t n = 1) { 203 size_t len = n * sizeof(T); 204 status_t ret = writeToData(buf, len, mValueWOffset /* data offset */, 205 getPaddedParameterSize() + getValueSize() /* max */); 206 if (OK == ret) { 207 mValueWOffset += len; 208 } 209 return ret; 210 } 211 212 /** 213 * Set the current value write offset to vsize. 214 * Together with getTotalSize(), can be used by getParameter to set replySize. 215 */ finishValueWrite()216 void finishValueWrite() { mParam.vsize = mValueWOffset - getPaddedParameterSize(); } 217 setStatus(status_t status)218 void setStatus(status_t status) { mParam.status = status; } 219 220 /** 221 * Overwrite the entire effect_param_t with input. 222 */ overwrite(const effect_param_t & param)223 status_t overwrite(const effect_param_t& param) { 224 EffectParamReader reader(param); 225 const auto size = reader.getTotalSize(); 226 if (size > getTotalSize()) { 227 return BAD_VALUE; 228 } 229 std::memcpy((void *)&mParam, (void *)&reader.getEffectParam(), size); 230 reset(); 231 mValueWOffset += reader.getValueSize(); 232 return OK; 233 } 234 235 /** 236 * Reset the offsets with underlying effect_param_t. 237 */ reset()238 void reset() { 239 EffectParamReader::reset(); 240 mParamWOffset = 0; 241 mValueWOffset = getPaddedParameterSize(); 242 } 243 toString()244 std::string toString() const { 245 std::ostringstream os; 246 os << EffectParamReader::toString(); 247 os << ", paramWOffset: " << mParamWOffset; 248 os << ", valueWOffset: " << mValueWOffset; 249 return os.str(); 250 } 251 252 private: 253 effect_param_t& mParam; 254 size_t mParamWOffset = 0; 255 size_t mValueWOffset = 0; 256 }; 257 258 } // namespace utils 259 } // namespace effect 260 } // namespace android 261