Home | History | Annotate | Download | only in task
      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