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