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 27 TaskProcess::TaskProcess() 28 : TaskGeneric(TaskGeneric::ETaskProcess) 29 { 30 31 } 32 33 TaskProcess::~TaskProcess() 34 { 35 } 36 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 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 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 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 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 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 337 TaskProcess::Param::Param(TaskCase::Value& val) 338 : mType(TaskProcess::EConst), 339 mValue(val) 340 { 341 342 } 343 344 TaskProcess::ParamType TaskProcess::Param::getType() 345 { 346 return mType; 347 } 348 349 android::String8& TaskProcess::Param::getParamString() 350 { 351 ASSERT((mType == TaskProcess::EId) || (mType == TaskProcess::EVal)); 352 return mString; 353 } 354 355 TaskCase::Value& TaskProcess::Param::getValue() 356 { 357 ASSERT(mType == TaskProcess::EConst); 358 return mValue; 359 } 360 361 TaskCase::Value* TaskProcess::Param::getValuePtr() 362 { 363 ASSERT(mType == TaskProcess::EConst); 364 return &mValue; 365 } 366