• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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