blob: 775126b7bf2e6499af48e8b6afca31cfc4f1f8f3 [file] [log] [blame]
/*
* Copyright (C) 2017-2020 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "PolicyParser"
#include <string.h>
#include <expat.h>
#include "iutils/CameraLog.h"
#include "PolicyParser.h"
namespace icamera {
#define PSYS_POLICY_FILE_NAME "psys_policy_profiles.xml"
PolicyParser::PolicyParser(PlatformData::StaticCfg *cfg) :
mStaticCfg(cfg),
mCurrentDataField(FIELD_INVALID),
pCurrentConf(nullptr) {
LOGXML("@%s", __func__);
CheckError(!mStaticCfg, VOID_VALUE, "@%s, cfg parameter is wrong", __func__);
mStaticCfg->mPolicyConfig.clear();
int ret = getDataFromXmlFile(PSYS_POLICY_FILE_NAME);
CheckError(ret != OK, VOID_VALUE,
"Failed to get policy profiles data frome %s", PSYS_POLICY_FILE_NAME);
}
/**
* This function will check which field that the parser parses to.
*
* The field is set to 2 types.
* FIELD_INVALID FIELD_GRAPH
*
* \param profiles: the pointer of the PolicyParser.
* \param name: the element's name.
* \param atts: the element's attribute.
*/
void PolicyParser::checkField(PolicyParser *profiles, const char *name, const char **atts)
{
LOGXML("@%s, name:%s", __func__, name);
if (strcmp(name, "PsysPolicyConfig") == 0) {
profiles->mCurrentDataField = FIELD_INVALID;
return;
} else if (strcmp(name, "graph") == 0) {
profiles->pCurrentConf = new PolicyConfig;
int idx = 0;
while (atts[idx]) {
const char* key = atts[idx];
const char* val = atts[idx + 1];
LOGXML("@%s, name:%s, atts[%d]:%s, atts[%d]:%s", __func__, name, idx, key, idx+1, val);
if (strcmp(key, "id") == 0) {
profiles->pCurrentConf->graphId = atoi(val);
} else if (strcmp(key, "description") == 0) {
profiles->pCurrentConf->policyDescription = val;
}
idx += 2;
}
profiles->mCurrentDataField = FIELD_GRAPH;
return;
}
LOGE("@%s, name:%s, atts[0]:%s, xml format wrong", __func__, name, atts[0]);
return;
}
void PolicyParser::handlePipeExecutor(PolicyParser *profiles, const char *name, const char **atts)
{
int idx = 0;
ExecutorPolicy policy;
while (atts[idx]) {
const char *key = atts[idx];
LOGXML("%s: name: %s, value: %s", __func__, atts[idx], atts[idx + 1]);
if (strcmp(key, "name") == 0) {
policy.exeName = atts[idx + 1];
} else if (strcmp(key, "pgs") == 0) {
parseXmlConvertStrings(atts[idx + 1], policy.pgList, convertCharToString);
} else if (strcmp(key, "op_modes") == 0) {
parseXmlConvertStrings(atts[idx + 1], policy.opModeList, atoi);
} else if (strcmp(key, "notify_policy") == 0) {
int notifyPolicy = std::stoi(atts[idx + 1]);
if (notifyPolicy >= 0 && notifyPolicy < POLICY_INVALID) {
policy.notifyPolicy = (ExecutorNotifyPolicy)notifyPolicy;
} else {
LOGW("Invalid notify policy value: %d", notifyPolicy);
}
} else if (strcmp(key, "cyclic_feedback_routine") == 0) {
parseXmlConvertStrings(atts[idx + 1], policy.cyclicFeedbackRoutineList, atoi);
} else if (strcmp(key, "cyclic_feedback_delay") == 0) {
parseXmlConvertStrings(atts[idx + 1], policy.cyclicFeedbackDelayList, atoi);
} else {
LOGW("Invalid policy attribute: %s", key);
}
idx += 2;
}
LOGXML("@%s, name:%s, atts[0]:%s", __func__, name, atts[0]);
profiles->pCurrentConf->pipeExecutorVec.push_back(policy);
}
void PolicyParser::handleExclusivePGs(PolicyParser *profiles, const char *name, const char **atts)
{
int idx = 0;
LOGXML("%s: name: %s, value: %s", __func__, atts[idx], atts[idx + 1]);
const char *key = atts[idx];
if (strcmp(key, "pgs") == 0) {
parseXmlConvertStrings(atts[idx + 1], profiles->pCurrentConf->exclusivePgs, convertCharToString);
} else {
LOGE("Invalid policy attribute %s in exclusive label.", key);
}
}
void PolicyParser::handleBundles(PolicyParser *profiles, const char *name, const char **atts)
{
int idx = 0;
LOGXML("%s: name: %s, value: %s", __func__, atts[idx], atts[idx + 1]);
const char *key = atts[idx];
CheckError(strcmp(key, "executors") != 0, VOID_VALUE, "Invalid policy attribute %s in bundle label.", key);
// The structure of a bundle looks like: "proc:0,post:1" which uses ',' to split
// different executors' names, and uses ':' to specify the executor's depth.
std::vector<std::string> bundledExecutors;
std::vector<int> depths;
std::vector<std::string> executors = CameraUtils::splitString(atts[idx + 1], ',');
for (const auto & item : executors) {
std::vector<std::string> executorDepth = CameraUtils::splitString(item.c_str(), ':');
CheckError(executorDepth.size() != 2, VOID_VALUE, "Invalid executor-depth mapping.");
bundledExecutors.push_back(executorDepth[0]);
depths.push_back(std::stoi(executorDepth[1]));
}
ExecutorDepth executorDepth = {bundledExecutors, depths};
profiles->pCurrentConf->bundledExecutorDepths.push_back(executorDepth);
}
void PolicyParser::handleShareReferPair(PolicyParser *profiles,
const char *name, const char **atts) {
// example: <shareReferPair pair="post_gdc_video_bayer:6,post_gdc_stills:6"/>
if (strcmp(atts[0], "pair") != 0) return;
int sz = strlen(atts[1]);
char src[sz + 1];
MEMCPY_S(src, sz, atts[1], sz);
src[sz] = '\0';
char* consumer = nullptr;
char* producer = strtok_r(src, ",", &consumer);
if (!consumer || !producer) return;
char* pPort = nullptr;
char* pName = strtok_r(producer, ":", &pPort);
char* cPort = nullptr;
char* cName = strtok_r(consumer, ":", &cPort);
if (!pPort || !cPort) return;
ShareReferIdDesc pPair;
ShareReferIdDesc cPair;
pPair.first = pName;
pPair.second = atoi(pPort);
cPair.first = cName;
cPair.second = atoi(cPort);
LOGXML("@%s, pair: %s:%d -> %s:%d", __func__,
pPair.first.c_str(), pPair.second, cPair.first.c_str(), cPair.second);
profiles->pCurrentConf->shareReferPairList.push_back(pPair);
profiles->pCurrentConf->shareReferPairList.push_back(cPair);
}
/**
* This function will handle all the sensor related elements.
*
* It will be called in the function startElement
*
* \param profiles: the pointer of the CameraParser.
* \param name: the element's name.
* \param atts: the element's attribute.
*/
void PolicyParser::handlePolicyConfig(PolicyParser *profiles, const char *name, const char **atts)
{
LOGXML("@%s, name:%s, atts[0]:%s", __func__, name, atts[0]);
if (strcmp(name, "pipe_executor") == 0) {
handlePipeExecutor(profiles, name, atts);
} else if (strcmp(name, "exclusive") == 0) {
handleExclusivePGs(profiles, name, atts);
} else if (strcmp(name, "bundle") == 0) {
handleBundles(profiles, name, atts);
} else if (strcmp(name, "enableBundleInSdv") == 0) {
profiles->pCurrentConf->enableBundleInSdv = (strcmp(atts[1], "true") == 0) ? true : false;
LOGXML("%s: enableBundleInSdv: %s", __func__, atts[1]);
} else if (strcmp(name, "shareReferPair") == 0) {
handleShareReferPair(profiles, name, atts);
}
}
/**
* the callback function of the libexpat for handling of one element start
*
* When it comes to the start of one element. This function will be called.
*
* \param userData: the pointer we set by the function XML_SetUserData.
* \param name: the element's name.
*/
void PolicyParser::startParseElement(void *userData, const char *name, const char **atts)
{
PolicyParser *profiles = reinterpret_cast<PolicyParser*>(userData);
if (profiles->mCurrentDataField == FIELD_INVALID) {
profiles->checkField(profiles, name, atts);
return;
}
switch (profiles->mCurrentDataField) {
case FIELD_GRAPH:
profiles->handlePolicyConfig(profiles, name, atts);
break;
default:
LOGE("@%s, line:%d, go to default handling", __func__, __LINE__);
break;
}
}
/**
* the callback function of the libexpat for handling of one element end
*
* When it comes to the end of one element. This function will be called.
*
* \param userData: the pointer we set by the function XML_SetUserData.
* \param name: the element's name.
*/
void PolicyParser::endParseElement(void *userData, const char *name)
{
LOGXML("@%s %s", __func__, name);
PolicyParser *profiles = reinterpret_cast<PolicyParser*>(userData);
if (strcmp(name, "graph") == 0) {
LOGXML("@%s, add policyConf, graphId: %d", __func__, profiles->pCurrentConf->graphId);
profiles->mStaticCfg->mPolicyConfig.push_back(*(profiles->pCurrentConf));
delete profiles->pCurrentConf;
profiles->pCurrentConf = nullptr;
profiles->mCurrentDataField = FIELD_INVALID;
}
}
} //namespace icamera