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