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