1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <memory>
20 #include <vector>
21
22 #include "Log.h"
23 #include "StringUtil.h"
24 #include "task/TaskProcess.h"
25 #include "SignalProcessingImpl.h"
26
TaskProcess()27 TaskProcess::TaskProcess()
28 : TaskGeneric(TaskGeneric::ETaskProcess)
29 {
30
31 }
32
~TaskProcess()33 TaskProcess::~TaskProcess()
34 {
35 }
36
run()37 TaskGeneric::ExecutionResult TaskProcess::run()
38 {
39 if (mType == EBuiltin) {
40 return doRun(true);
41 } else {
42 if (mSp.get() == NULL) {
43 mSp.reset(new SignalProcessingImpl());
44 if (!mSp->init(SignalProcessingImpl::MAIN_PROCESSING_SCRIPT)) {
45 mSp.reset(NULL);
46 return TaskGeneric::EResultError;
47 }
48 }
49 return doRun(false);
50 }
51 }
52
53 // Allocate Buffers and Values to pass to builtin functions
prepareParams(std::vector<TaskProcess::Param> & list,const bool * paramTypes,std::unique_ptr<void_ptr[]> & ptrs,std::unique_ptr<UniqueValue[]> & values,std::unique_ptr<UniqueBuffer[]> & buffers,bool isInput)54 bool TaskProcess::prepareParams(std::vector<TaskProcess::Param>& list,
55 const bool* paramTypes,
56 std::unique_ptr<void_ptr[]>& ptrs,
57 std::unique_ptr<UniqueValue[]>& values,
58 std::unique_ptr<UniqueBuffer[]>& buffers,
59 bool isInput)
60 {
61 size_t N = list.size();
62
63 LOGD("TaskProcess::prepareParams N = %d", N);
64 ptrs.reset(new void_ptr[N]);
65 if (ptrs.get() == NULL) {
66 LOGE("alloc failed");
67 return false;
68 }
69 // set to NULL to detect illegal access
70 bzero(ptrs.get(), N * sizeof(void_ptr));
71 values.reset(new UniqueValue[N]);
72 if (values.get() == NULL) {
73 LOGE("alloc failed");
74 return false;
75 }
76 buffers.reset(new UniqueBuffer[N]);
77 if (buffers.get() == NULL) {
78 LOGE("alloc failed");
79 return false;
80 }
81
82 void_ptr* voidPtrs = ptrs.get();
83 UniqueValue* valuesPtr = values.get();
84 UniqueBuffer* buffersPtr = buffers.get();
85 for (size_t i = 0; i < N; i++) {
86 if ((paramTypes != NULL) && paramTypes[i] && (list[i].getType() != EId)) {
87 LOGE("mismatching types %d %d", paramTypes[i], list[i].getType());
88 return false;
89 }
90 if ((paramTypes != NULL) && !paramTypes[i] && (list[i].getType() == EId)) {
91 LOGE("mismatching types %d %d", paramTypes[i], list[i].getType());
92 return false;
93 }
94 switch(list[i].getType()) {
95 case EId: {
96 std::unique_ptr<android::sp<Buffer> > buffer(new android::sp<Buffer>());
97 if (buffer.get() == NULL) {
98 LOGE("alloc failed");
99 return false;
100 }
101 if (isInput) {
102 *(buffer.get()) = getTestCase()->findBuffer(list[i].getParamString());
103 if (buffer.get()->get() == NULL) {
104 LOGE("find failed");
105 return false;
106 }
107 LOGD("input buffer len %d stereo %d", (*buffer.get())->getSize(),
108 (*buffer.get())->isStereo());
109 }
110 buffersPtr[i].reset(buffer.release());
111 voidPtrs[i] = buffersPtr[i].get();
112 }
113 break;
114 case EVal: {
115 valuesPtr[i].reset(new TaskCase::Value());
116 if (isInput) {
117 if (!getTestCase()->findValue(list[i].getParamString(), *(valuesPtr[i].get()))) {
118 LOGE("find %s failed", list[i].getParamString().string());
119 return false;
120 }
121 }
122 voidPtrs[i] = valuesPtr[i].get();
123 }
124 break;
125 case EConst: {
126 if (!isInput) {
127 LOGE("const for output");
128 return false;
129 }
130 voidPtrs[i] = list[i].getValuePtr();
131
132 if (list[i].getValue().getType() == TaskCase::Value::ETypeDouble) {
133 LOGD(" %f", list[i].getValue().getDouble());
134 } else {
135 LOGD(" %lld", list[i].getValue().getInt64());
136 }
137 }
138 break;
139 }
140 LOGD("TaskProcess::prepareParams %d-th, const 0x%x", i, voidPtrs[i]);
141 }
142 return true;
143 }
144
145 // run builtin function by searching BuiltinProcessing::BUINTIN_FN_TABLE
doRun(bool builtIn)146 TaskGeneric::ExecutionResult TaskProcess::doRun(bool builtIn)
147 {
148 BuiltinProcessing::BuiltinInfo* info = NULL;
149 if (builtIn) {
150 for (int i = 0; i < BuiltinProcessing::N_BUILTIN_FNS; i++) {
151 if (StringUtil::compare(mName, BuiltinProcessing::BUINTIN_FN_TABLE[i].mName) == 0) {
152 info = &BuiltinProcessing::BUINTIN_FN_TABLE[i];
153 break;
154 }
155 }
156 if (info == NULL) {
157 LOGE("TaskProcess::runBuiltin no match for %s", mName.string());
158 return TaskGeneric::EResultError;
159 }
160 if (mInput.size() != info->mNInput) {
161 LOGE("TaskProcess::runBuiltin size mismatch %d vs %d", mInput.size(), info->mNInput);
162 return TaskGeneric::EResultError;
163 }
164 if (mOutput.size() != info->mNOutput) {
165 LOGE("TaskProcess::runBuiltin size mismatch %d vs %d", mOutput.size(), info->mNOutput);
166 return TaskGeneric::EResultError;
167 }
168 }
169 // This is for passing to builtin fns. Just void pts will be cleared in exit
170 std::unique_ptr<void_ptr[]> inputs;
171 // This is for holding Value instances. Will be destroyed in exit
172 std::unique_ptr<UniqueValue[]> inputValues;
173 // This is for holding android::sp<Buffer>. Buffer itself is from the global map.
174 std::unique_ptr<UniqueBuffer[]> inputBuffers;
175
176 std::unique_ptr<void_ptr[]> outputs;
177 // Value is created here. Builtin function just need to set it.
178 std::unique_ptr<UniqueValue[]> outputValues;
179 // Buffer itself should be allocated by the builtin function itself.
180 std::unique_ptr<UniqueBuffer[]> outputBuffers;
181
182 if (!prepareParams(mInput, builtIn ? info->mInputTypes : NULL, inputs, inputValues,
183 inputBuffers, true)) {
184 return TaskGeneric::EResultError;
185 }
186
187 if (!prepareParams(mOutput, builtIn ? info->mOutputTypes : NULL, outputs, outputValues,
188 outputBuffers, false)) {
189 return TaskGeneric::EResultError;
190 }
191
192 TaskGeneric::ExecutionResult result;
193 if (builtIn) {
194 result = (mBuiltin.*(info->mFunction))(inputs.get(), outputs.get());
195 } else {
196 std::unique_ptr<bool[]> inputTypes(new bool[mInput.size()]);
197 for (size_t i = 0; i < mInput.size(); i++) {
198 (inputTypes.get())[i] = mInput[i].isIdType();
199 }
200 std::unique_ptr<bool[]> outputTypes(new bool[mOutput.size()]);
201 for (size_t i = 0; i < mOutput.size(); i++) {
202 (outputTypes.get())[i] = mOutput[i].isIdType();
203 }
204 result = mSp->run( mName,
205 mInput.size(), inputTypes.get(), inputs.get(),
206 mOutput.size(), outputTypes.get(), outputs.get());
207 }
208 if ((result == TaskGeneric::EResultOK) || (result == TaskGeneric::EResultFail)
209 || (result == TaskGeneric::EResultPass)) {
210 // try to save result
211 bool saveResultFailed = false;
212 for (size_t i = 0; i < mOutput.size(); i++) {
213 if (mOutput[i].isIdType()) { // Buffer
214 android::sp<Buffer>* bufferp =
215 reinterpret_cast<android::sp<Buffer>*>((outputs.get())[i]);
216 if (!getTestCase()->registerBuffer(mOutput[i].getParamString(), *bufferp)) {
217 // maybe already there, try update
218 if (!getTestCase()->updateBuffer(mOutput[i].getParamString(), *bufferp)) {
219 LOGE("cannot register / update %d-th output Buffer for builtin fn %s",
220 i, mName.string());
221 saveResultFailed = true; // mark failure, but continue
222 }
223 }
224 } else { // Value
225 TaskCase::Value* valuep =
226 reinterpret_cast<TaskCase::Value*>((outputs.get())[i]);
227 if (!getTestCase()->registerValue(mOutput[i].getParamString(), *valuep)) {
228 if (!getTestCase()->updateValue(mOutput[i].getParamString(), *valuep)) {
229 LOGE("cannot register / update %d-th output Value for builtin fn %s",
230 i, mName.string());
231 saveResultFailed = true; // mark failure, but continue
232 }
233 }
234 }
235 }
236 if (saveResultFailed) {
237 LOGE("TaskProcess::runBuiltin cannot save result");
238 return TaskGeneric::EResultError;
239 }
240 }
241 LOGV("TaskProcess::runBuiltin return %d", result);
242 return result;
243 }
244
parseParams(std::vector<TaskProcess::Param> & list,const char * str,bool isInput)245 bool TaskProcess::parseParams(std::vector<TaskProcess::Param>& list, const char* str, bool isInput)
246 {
247 LOGV("TaskProcess::parseParams will parse %s", str);
248 android::String8 paramStr(str);
249 std::unique_ptr<std::vector<android::String8>> paramTokens(StringUtil::split(paramStr, ','));
250 if (paramTokens.get() == NULL) {
251 LOGE("split failed");
252 return false;
253 }
254 std::vector<android::String8>& tokens = *(paramTokens.get());
255 for (size_t i = 0; i < tokens.size(); i++) {
256 std::unique_ptr<std::vector<android::String8>> itemTokens(StringUtil::split(tokens[i],
257 ':'));
258 if (itemTokens.get() == NULL) {
259 LOGE("split failed");
260 return false;
261 }
262 if (itemTokens->size() != 2) {
263 LOGE("size mismatch %d", itemTokens->size());
264 return false;
265 }
266 std::vector<android::String8>& item = *(itemTokens.get());
267 if (StringUtil::compare(item[0], "id") == 0) {
268 Param param(EId, item[1]);
269 list.push_back(param);
270 LOGD(" id %s", param.getParamString().string());
271 } else if (StringUtil::compare(item[0], "val") == 0) {
272 Param param(EVal, item[1]);
273 list.push_back(param);
274 LOGD(" val %s", param.getParamString().string());
275 } else if (isInput && (StringUtil::compare(item[0], "consti") == 0)) {
276 int64_t value = atoll(item[1].string());
277 TaskCase::Value v(value);
278 Param param(v);
279 list.push_back(param);
280 LOGD("consti %lld", value);
281 } else if (isInput && (StringUtil::compare(item[0], "constf") == 0)) {
282 double value = atof(item[1].string());
283 TaskCase::Value v(value);
284 Param param(v);
285 list.push_back(param);
286 LOGD("constf %f", value);
287 } else {
288 LOGE("unrecognized word %s", item[0].string());
289 return false;
290 }
291 LOGV("TaskProcess::parseParams %d-th type %d", i, list[i].getType());
292 }
293 return true;
294 }
295
parseAttribute(const android::String8 & name,const android::String8 & value)296 bool TaskProcess::parseAttribute(const android::String8& name, const android::String8& value)
297 {
298 if (StringUtil::compare(name, "method") == 0) {
299 std::unique_ptr<std::vector<android::String8> > tokenPtr(StringUtil::split(value, ':'));
300 std::vector<android::String8>* tokens = tokenPtr.get();
301 if (tokens == NULL) {
302 LOGE("split failed");
303 return false;
304 }
305 if (tokens->size() != 2) {
306 LOGE("cannot parse attr %s %s", name.string(), value.string());
307 return false;
308 }
309 if (StringUtil::compare(tokens->at(0), "builtin") == 0) {
310 mType = EBuiltin;
311 } else if (StringUtil::compare(tokens->at(0), "script") == 0) {
312 mType = EScript;
313 } else {
314 LOGE("cannot parse attr %s %s", name.string(), value.string());
315 return false;
316 }
317 mName.append(tokens->at(1));
318 return true;
319 } else if (StringUtil::compare(name, "input") == 0) {
320 return parseParams(mInput, value, true);
321 } else if (StringUtil::compare(name, "output") == 0) {
322 return parseParams(mOutput, value, false);
323 } else {
324 LOGE("cannot parse attr %s %s", name.string(), value.string());
325 return false;
326 }
327 }
328
Param(TaskProcess::ParamType type,android::String8 & string)329 TaskProcess::Param::Param(TaskProcess::ParamType type, android::String8& string)
330 : mType(type),
331 mString(string)
332 {
333 ASSERT((type == TaskProcess::EId) || (type == TaskProcess::EVal));
334
335 }
336
Param(TaskCase::Value & val)337 TaskProcess::Param::Param(TaskCase::Value& val)
338 : mType(TaskProcess::EConst),
339 mValue(val)
340 {
341
342 }
343
getType()344 TaskProcess::ParamType TaskProcess::Param::getType()
345 {
346 return mType;
347 }
348
getParamString()349 android::String8& TaskProcess::Param::getParamString()
350 {
351 ASSERT((mType == TaskProcess::EId) || (mType == TaskProcess::EVal));
352 return mString;
353 }
354
getValue()355 TaskCase::Value& TaskProcess::Param::getValue()
356 {
357 ASSERT(mType == TaskProcess::EConst);
358 return mValue;
359 }
360
getValuePtr()361 TaskCase::Value* TaskProcess::Param::getValuePtr()
362 {
363 ASSERT(mType == TaskProcess::EConst);
364 return &mValue;
365 }
366