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 <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             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 
    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