16ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa/*
26ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * Copyright 2017, The Android Open Source Project
36ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa *
46ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * Licensed under the Apache License, Version 2.0 (the "License");
56ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * you may not use this file except in compliance with the License.
66ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * You may obtain a copy of the License at
76ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa *
86ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa *     http://www.apache.org/licenses/LICENSE-2.0
96ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa *
106ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * Unless required by applicable law or agreed to in writing, software
116ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * distributed under the License is distributed on an "AS IS" BASIS,
126ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * See the License for the specific language governing permissions and
146ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa * limitations under the License.
156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa */
166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa//#define LOG_NDEBUG 0
186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa#define LOG_TAG "MediaCodecsXmlParser"
196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
202be091cebb9462b63d7160d0fa2cfa8703973a69Pawin Vongmasa#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
22cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa#include <utils/Log.h>
236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa#include <media/stagefright/MediaErrors.h>
24cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa#include <media/stagefright/omx/OMXUtils.h>
256ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa#include <sys/stat.h>
266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa#include <expat.h>
276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
28cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa#include <cctype>
29cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa#include <algorithm>
306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
316ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasanamespace android {
326ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
33cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasanamespace {
346ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
35cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa/**
36cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * Search for a file in a list of search directories.
37cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa *
38cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * For each string `searchDir` in `searchDirs`, `searchDir/fileName` will be
39cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * tested whether it is a valid file name or not. If it is a valid file name,
40cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * the concatenated name (`searchDir/fileName`) will be stored in the output
41cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * variable `outPath`, and the function will return `true`. Otherwise, the
42cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * search continues until the `nullptr` element in `searchDirs` is reached, at
43cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * which point the function returns `false`.
44cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa *
45cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * \param[in] searchDirs Null-terminated array of search paths.
46cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * \param[in] fileName Name of the file to search.
47cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * \param[out] outPath Full path of the file. `outPath` will hold a valid file
48cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * name if the return value of this function is `true`.
49cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * \return `true` if some element in `searchDirs` combined with `fileName` is a
50cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa * valid file name; `false` otherwise.
51cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa */
52cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool findFileInDirs(
53cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char* const* searchDirs,
54cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char *fileName,
55cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        std::string *outPath) {
56cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    for (; *searchDirs != nullptr; ++searchDirs) {
57cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        *outPath = std::string(*searchDirs) + "/" + fileName;
58cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        struct stat fileStat;
59cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (stat(outPath->c_str(), &fileStat) == 0 &&
60cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                S_ISREG(fileStat.st_mode)) {
616ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return true;
626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
636ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
646ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return false;
656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
666ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
67cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool strnEq(const char* s1, const char* s2, size_t count) {
68cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return strncmp(s1, s2, count) == 0;
696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
706ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
71cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool strEq(const char* s1, const char* s2) {
72cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return strcmp(s1, s2) == 0;
736ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
75cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool striEq(const char* s1, const char* s2) {
76cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return strcasecmp(s1, s2) == 0;
77cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
79cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool strHasPrefix(const char* test, const char* prefix) {
80cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return strnEq(test, prefix, strlen(prefix));
81cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
82cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
83cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool parseBoolean(const char* s) {
84cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return striEq(s, "y") ||
85cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            striEq(s, "yes") ||
86cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            striEq(s, "t") ||
87cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            striEq(s, "true") ||
88cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            striEq(s, "1");
89cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
90cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
91cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasastatus_t limitFoundMissingAttr(const char* name, const char *attr, bool found = true) {
92cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    ALOGE("limit '%s' with %s'%s' attribute", name,
93cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            (found ? "" : "no "), attr);
94cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return -EINVAL;
95cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
96cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
97cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasastatus_t limitError(const char* name, const char *msg) {
98cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    ALOGE("limit '%s' %s", name, msg);
99cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return -EINVAL;
100cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
101cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
102cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasastatus_t limitInvalidAttr(const char* name, const char* attr, const char* value) {
103cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name,
104cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            attr, value);
105cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return -EINVAL;
106cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
107cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
108cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}; // unnamed namespace
109cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
110cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconstexpr char const* MediaCodecsXmlParser::defaultSearchDirs[];
111cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconstexpr char const* MediaCodecsXmlParser::defaultMainXmlName;
112cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconstexpr char const* MediaCodecsXmlParser::defaultPerformanceXmlName;
113cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconstexpr char const* MediaCodecsXmlParser::defaultProfilingResultsXmlPath;
114cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
115cbdeea977b79c41910b004cffcb80d81265853e8Pawin VongmasaMediaCodecsXmlParser::MediaCodecsXmlParser(
116cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char* const* searchDirs,
117cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char* mainXmlName,
118cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char* performanceXmlName,
119cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char* profilingResultsXmlPath) :
120cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mParsingStatus(NO_INIT),
121cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mUpdate(false),
122cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCodecCounter(0) {
123cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    std::string path;
124cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (findFileInDirs(searchDirs, mainXmlName, &path)) {
125cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        parseTopLevelXMLFile(path.c_str(), false);
1266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    } else {
127cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        ALOGE("Cannot find %s", mainXmlName);
128cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mParsingStatus = NAME_NOT_FOUND;
1296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
130cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (findFileInDirs(searchDirs, performanceXmlName, &path)) {
131cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        parseTopLevelXMLFile(path.c_str(), true);
132cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    }
133cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (profilingResultsXmlPath != nullptr) {
134cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        parseTopLevelXMLFile(profilingResultsXmlPath, true);
1356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
1366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
1376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
138cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasabool MediaCodecsXmlParser::parseTopLevelXMLFile(
139cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const char *codecs_xml,
140cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        bool ignore_errors) {
1416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // get href_base
1426ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    const char *href_base_end = strrchr(codecs_xml, '/');
143cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (href_base_end != nullptr) {
144cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mHrefBase = std::string(codecs_xml, href_base_end - codecs_xml + 1);
1456ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
1466ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
147cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mParsingStatus = OK; // keeping this here for safety
1486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    mCurrentSection = SECTION_TOPLEVEL;
1496ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1506ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    parseXMLFile(codecs_xml);
1516ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
152cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mParsingStatus != OK) {
153cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        ALOGW("parseTopLevelXMLFile(%s) failed", codecs_xml);
1546ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        if (ignore_errors) {
155cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mParsingStatus = OK;
156cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return false;
1576ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
158cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mCodecMap.clear();
159cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        return false;
1606ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
161cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return true;
1626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
1636ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1646ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin VongmasaMediaCodecsXmlParser::~MediaCodecsXmlParser() {
1656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
1666ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1676ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasavoid MediaCodecsXmlParser::parseXMLFile(const char *path) {
1686ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    FILE *file = fopen(path, "r");
1696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
170cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (file == nullptr) {
1716ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGW("unable to open media codecs configuration xml file: %s", path);
172cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mParsingStatus = NAME_NOT_FOUND;
1736ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return;
1746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
1756ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
176cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    XML_Parser parser = ::XML_ParserCreate(nullptr);
177cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    LOG_FATAL_IF(parser == nullptr, "XML_MediaCodecsXmlParserCreate() failed.");
1786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    ::XML_SetUserData(parser, this);
1806ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    ::XML_SetElementHandler(
1816ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
1826ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
183cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    static constexpr int BUFF_SIZE = 512;
184cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (mParsingStatus == OK) {
1856ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
186cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (buff == nullptr) {
1876ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("failed in call to XML_GetBuffer()");
188cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mParsingStatus = UNKNOWN_ERROR;
1896ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
1906ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
1916ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1926ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
1936ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        if (bytes_read < 0) {
1946ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("failed in call to read");
195cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mParsingStatus = ERROR_IO;
1966ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
1976ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
1986ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1996ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
2006ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        if (status != XML_STATUS_OK) {
2016ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
202cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mParsingStatus = ERROR_MALFORMED;
2036ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
2046ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2056ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2066ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        if (bytes_read == 0) {
2076ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
2086ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2096ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
2106ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2116ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    ::XML_ParserFree(parser);
2126ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2136ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    fclose(file);
214cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    file = nullptr;
2156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
2166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa// static
2186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasavoid MediaCodecsXmlParser::StartElementHandlerWrapper(
2196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        void *me, const char *name, const char **attrs) {
220cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    static_cast<MediaCodecsXmlParser*>(me)->startElementHandler(name, attrs);
2216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
2226ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa// static
2246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasavoid MediaCodecsXmlParser::EndElementHandlerWrapper(void *me, const char *name) {
225cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    static_cast<MediaCodecsXmlParser*>(me)->endElementHandler(name);
2266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
2276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::includeXMLFile(const char **attrs) {
229cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *href = nullptr;
2306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
231cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
232cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "href")) {
233cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
2346ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
2356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
236cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            href = attrs[i];
2376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
2386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("includeXMLFile: unrecognized attribute: %s", attrs[i]);
2396ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
2406ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
2426ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
2436ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2446ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // For security reasons and for simplicity, file names can only contain
2456ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
2466ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    for (i = 0; href[i] != '\0'; i++) {
2476ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        if (href[i] == '.' || href[i] == '_' ||
2486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                (href[i] >= '0' && href[i] <= '9') ||
2496ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                (href[i] >= 'A' && href[i] <= 'Z') ||
2506ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                (href[i] >= 'a' && href[i] <= 'z')) {
2516ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            continue;
2526ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2536ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("invalid include file name: %s", href);
2546ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
2556ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
2566ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
257cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    std::string filename = href;
258cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (filename.compare(0, 13, "media_codecs_") != 0 ||
259cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            filename.compare(filename.size() - 4, 4, ".xml") != 0) {
2606ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("invalid include file name: %s", href);
2616ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
2626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
263cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    filename.insert(0, mHrefBase);
2646ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    parseXMLFile(filename.c_str());
266cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mParsingStatus;
2676ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
2686ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasavoid MediaCodecsXmlParser::startElementHandler(
2706ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        const char *name, const char **attrs) {
271cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mParsingStatus != OK) {
2726ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return;
2736ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
2746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2756ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    bool inType = true;
2766ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
277cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (strEq(name, "Include")) {
278cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mParsingStatus = includeXMLFile(attrs);
279cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (mParsingStatus == OK) {
280cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mSectionStack.push_back(mCurrentSection);
2816ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            mCurrentSection = SECTION_INCLUDE;
2826ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2836ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return;
2846ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
2856ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2866ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    switch (mCurrentSection) {
2876ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_TOPLEVEL:
2886ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
289cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Decoders")) {
2906ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_DECODERS;
291cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(name, "Encoders")) {
2926ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_ENCODERS;
293cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(name, "Settings")) {
2946ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_SETTINGS;
2956ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
2966ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
2976ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
2986ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
2996ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_SETTINGS:
3006ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
301cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Setting")) {
302cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus = addSettingFromAttributes(attrs);
3036ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3046ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3056ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3066ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3076ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODERS:
3086ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
309cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "MediaCodec")) {
310cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus =
3116ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                    addMediaCodecFromAttributes(false /* encoder */, attrs);
3126ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3136ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_DECODER;
3146ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODERS:
3196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
320cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "MediaCodec")) {
321cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus =
3226ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                    addMediaCodecFromAttributes(true /* encoder */, attrs);
3236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_ENCODER;
3256ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODER:
3306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODER:
3316ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
332cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Quirk")) {
333cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus = addQuirk(attrs);
334cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(name, "Type")) {
335cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus = addTypeFromAttributes(attrs,
336cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        (mCurrentSection == SECTION_ENCODER));
3376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection =
338cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        (mCurrentSection == SECTION_DECODER ?
339cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
3406ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3426ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        inType = false;
3436ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        // fall through
3446ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3456ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODER_TYPE:
3466ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODER_TYPE:
3476ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
3486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            // ignore limits and features specified outside of type
349cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            bool outside = !inType &&
350cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    mCurrentType == mCurrentCodec->second.typeMap.end();
351cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (outside &&
352cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    (strEq(name, "Limit") || strEq(name, "Feature"))) {
3536ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGW("ignoring %s specified outside of a Type", name);
354cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(name, "Limit")) {
355cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus = addLimit(attrs);
356cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(name, "Feature")) {
357cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mParsingStatus = addFeature(attrs);
3586ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3596ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3606ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3616ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        default:
3636ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3646ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
3656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3666ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
3676ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3686ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasavoid MediaCodecsXmlParser::endElementHandler(const char *name) {
369cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mParsingStatus != OK) {
3706ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return;
3716ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
3726ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3736ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    switch (mCurrentSection) {
3746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_SETTINGS:
3756ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
376cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Settings")) {
3776ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_TOPLEVEL;
3786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3806ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3816ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3826ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODERS:
3836ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
384cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Decoders")) {
3856ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_TOPLEVEL;
3866ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3876ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3886ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3896ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3906ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODERS:
3916ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
392cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Encoders")) {
3936ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_TOPLEVEL;
3946ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
3956ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
3966ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
3976ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
3986ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODER_TYPE:
3996ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODER_TYPE:
4006ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
401cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Type")) {
4026ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection =
403cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        (mCurrentSection == SECTION_DECODER_TYPE ?
404cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        SECTION_DECODER : SECTION_ENCODER);
4056ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
406cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType = mCurrentCodec->second.typeMap.end();
4076ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
4086ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
4096ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
4106ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4116ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_DECODER:
4126ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
413cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "MediaCodec")) {
4146ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_DECODERS;
4156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentName.clear();
4166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
4176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
4186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
4196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4206ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_ENCODER:
4216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
422cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "MediaCodec")) {
4236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentSection = SECTION_ENCODERS;
4246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                mCurrentName.clear();
4256ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
4266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
4276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
4286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        case SECTION_INCLUDE:
4306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        {
431cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(name, "Include") && (mSectionStack.size() > 0)) {
432cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentSection = mSectionStack.back();
433cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mSectionStack.pop_back();
4346ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
4356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
4366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
4376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        default:
4396ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            break;
4406ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
4416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4426ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
4436ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4446ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addSettingFromAttributes(const char **attrs) {
445cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *name = nullptr;
446cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *value = nullptr;
447cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *update = nullptr;
4486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
4496ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
450cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
451cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
452cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
4536ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addSettingFromAttributes: name is null");
4546ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
4556ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
456cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            name = attrs[i];
457cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "value")) {
458cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
4596ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addSettingFromAttributes: value is null");
4606ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
4616ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
462cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            value = attrs[i];
463cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "update")) {
464cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
4656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addSettingFromAttributes: update is null");
4666ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
4676ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
468cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            update = attrs[i];
4696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
4706ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addSettingFromAttributes: unrecognized attribute: %s", attrs[i]);
4716ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
4726ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
4736ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
4746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
4756ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
476cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (name == nullptr || value == nullptr) {
4776ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("addSettingFromAttributes: name or value unspecified");
4786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
4796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
4806ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
481cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    // Boolean values are converted to "0" or "1".
482cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (strHasPrefix(name, "supports-")) {
483cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        value = parseBoolean(value) ? "1" : "0";
484cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    }
485cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
486cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mUpdate = (update != nullptr) && parseBoolean(update);
487cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    auto attribute = mServiceAttributeMap.find(name);
488cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (attribute == mServiceAttributeMap.end()) { // New attribute name
489cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (mUpdate) {
490cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            ALOGE("addSettingFromAttributes: updating non-existing setting");
491cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return -EINVAL;
492cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
493cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mServiceAttributeMap.insert(Attribute(name, value));
494cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    } else { // Existing attribute name
495cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (!mUpdate) {
496cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            ALOGE("addSettingFromAttributes: adding existing setting");
497cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
498cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        attribute->second = value;
4996ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
5006ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5016ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
5026ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
5036ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5046ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addMediaCodecFromAttributes(
5056ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        bool encoder, const char **attrs) {
506cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *name = nullptr;
507cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *type = nullptr;
508cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *update = nullptr;
5096ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5106ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
511cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
512cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
513cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
5146ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addMediaCodecFromAttributes: name is null");
5156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
5166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
517cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            name = attrs[i];
518cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "type")) {
519cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
5206ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addMediaCodecFromAttributes: type is null");
5216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
5226ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
523cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            type = attrs[i];
524cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "update")) {
525cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
5266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addMediaCodecFromAttributes: update is null");
5276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
5286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
529cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            update = attrs[i];
5306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
5316ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addMediaCodecFromAttributes: unrecognized attribute: %s", attrs[i]);
5326ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
5336ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
5346ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
5356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
5366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
537cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (name == nullptr) {
5386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("addMediaCodecFromAttributes: name not found");
5396ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
5406ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
5416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
542cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mUpdate = (update != nullptr) && parseBoolean(update);
543cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCurrentCodec = mCodecMap.find(name);
544cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mCurrentCodec == mCodecMap.end()) { // New codec name
545cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (mUpdate) {
546cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            ALOGE("addMediaCodecFromAttributes: updating non-existing codec");
547cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return -EINVAL;
548cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
549cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // Create a new codec in mCodecMap
550cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mCurrentCodec = mCodecMap.insert(
551cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                Codec(name, CodecProperties())).first;
552cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (type != nullptr) {
553cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType = mCurrentCodec->second.typeMap.insert(
554cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    Type(type, AttributeMap())).first;
555cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else {
556cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType = mCurrentCodec->second.typeMap.end();
557cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
558cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mCurrentCodec->second.isEncoder = encoder;
559cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mCurrentCodec->second.order = mCodecCounter++;
560cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    } else { // Existing codec name
561cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (!mUpdate) {
562cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            ALOGE("addMediaCodecFromAttributes: adding existing codec");
563cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return -EINVAL;
564cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
565cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (type != nullptr) {
566cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType = mCurrentCodec->second.typeMap.find(type);
567cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
5686ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addMediaCodecFromAttributes: updating non-existing type");
5696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
5706ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
571cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else {
572cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // This should happen only when the codec has at most one type.
573cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType = mCurrentCodec->second.typeMap.begin();
5746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
5756ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
5766ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5776ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
5786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
5796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5806ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
581cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *name = nullptr;
5826ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
5836ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
584cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
585cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
586cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
5876ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addQuirk: name is null");
5886ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
5896ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
590cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            name = attrs[i];
5916ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
5926ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addQuirk: unrecognized attribute: %s", attrs[i]);
5936ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
5946ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
5956ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
5966ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
5976ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
598cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (name == nullptr) {
5996ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("addQuirk: name not found");
6006ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
6016ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
6026ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
603cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCurrentCodec->second.quirkSet.emplace(name);
6046ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
6056ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
6066ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
6076ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addTypeFromAttributes(const char **attrs, bool encoder) {
608cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *name = nullptr;
609cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *update = nullptr;
6106ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
6116ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
612cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
613cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
614cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
6156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addTypeFromAttributes: name is null");
6166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
6176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
618cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            name = attrs[i];
619cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "update")) {
620cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
6216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                ALOGE("addTypeFromAttributes: update is null");
6226ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                return -EINVAL;
6236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
624cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            update = attrs[i];
6256ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
6266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addTypeFromAttributes: unrecognized attribute: %s", attrs[i]);
6276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
6286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
6296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
6306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
6316ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
632cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (name == nullptr) {
6336ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
6346ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
6356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
636cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCurrentCodec->second.isEncoder = encoder;
637cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCurrentType = mCurrentCodec->second.typeMap.find(name);
6386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    if (!mUpdate) {
639cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (mCurrentType != mCurrentCodec->second.typeMap.end()) {
6406ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addTypeFromAttributes: re-defining existing type without update");
6416ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
6426ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
643cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        mCurrentType = mCurrentCodec->second.typeMap.insert(
644cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                Type(name, AttributeMap())).first;
645cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    } else if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
6466ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("addTypeFromAttributes: updating non-existing type");
6476ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
6486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
6496ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
6506ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
6516ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addLimit(const char **attrs) {
652cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_name = nullptr;
653cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_default = nullptr;
654cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_in = nullptr;
655cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_max = nullptr;
656cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_min = nullptr;
657cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_range = nullptr;
658cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_ranges = nullptr;
659cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_scale = nullptr;
660cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char* a_value = nullptr;
6616ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
6626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
663cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
664cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
665cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
666cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: name is null");
667cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
668cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
669cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_name = attrs[i];
670cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "default")) {
671cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
672cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: default is null");
673cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
674cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
675cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_default = attrs[i];
676cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "in")) {
677cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
678cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: in is null");
679cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
680cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
681cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_in = attrs[i];
682cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "max")) {
683cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
684cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: max is null");
685cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
686cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
687cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_max = attrs[i];
688cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "min")) {
689cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
690cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: min is null");
691cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
692cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
693cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_min = attrs[i];
694cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "range")) {
695cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
696cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: range is null");
697cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
698cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
699cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_range = attrs[i];
700cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "ranges")) {
701cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
702cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: ranges is null");
703cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
704cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
705cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_ranges = attrs[i];
706cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "scale")) {
707cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
708cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: scale is null");
709cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
710cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
711cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_scale = attrs[i];
712cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "value")) {
713cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
714cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addLimit: value is null");
715cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
716cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
717cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            a_value = attrs[i];
7186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
7196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addLimit: unrecognized limit: %s", attrs[i]);
7206ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
7216ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
7226ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
7236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
7246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
725cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (a_name == nullptr) {
7266ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGE("limit with no 'name' attribute");
7276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
7286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
7296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
7306ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio,
7316ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // measured-frame-rate, measured-blocks-per-second: range
7326ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // quality: range + default + [scale]
7336ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    // complexity: range + default
734cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
7356ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGW("ignoring null type");
7366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return OK;
7376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
7386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
739cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    std::string range;
740cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (strEq(a_name, "aspect-ratio") ||
741cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "bitrate") ||
742cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "block-count") ||
743cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "blocks-per-second") ||
744cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "complexity") ||
745cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "frame-rate") ||
746cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "quality") ||
747cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "size") ||
748cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strEq(a_name, "measured-blocks-per-second") ||
749cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            strHasPrefix(a_name, "measured-frame-rate-")) {
750cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // "range" is specified in exactly one of the following forms:
751cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // 1) min-max
752cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // 2) value-value
753cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // 3) range
754cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_min != nullptr && a_max != nullptr) {
755cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // min-max
756cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (a_range != nullptr || a_value != nullptr) {
757cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitError(a_name, "has 'min' and 'max' as well as 'range' or "
7586ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa                        "'value' attributes");
7596ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
760cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range = a_min;
761cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range += '-';
762cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range += a_max;
763cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (a_min != nullptr || a_max != nullptr) {
764cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitError(a_name, "has only 'min' or 'max' attribute");
765cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (a_value != nullptr) {
766cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // value-value
767cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (a_range != nullptr) {
768cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitError(a_name, "has both 'range' and 'value' attributes");
7696ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
770cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range = a_value;
771cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range += '-';
772cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range += a_value;
773cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (a_range == nullptr) {
774cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitError(a_name, "with no 'range', 'value' or 'min'/'max' attributes");
775cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else {
776cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // range
777cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            range = a_range;
7786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
7796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
780cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        // "aspect-ratio" requires some special treatment.
781cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(a_name, "aspect-ratio")) {
782cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "aspect-ratio" must have "in".
783cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (a_in == nullptr) {
784cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "in", false);
785cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
786cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "in" must be either "pixels" or "blocks".
787cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (!strEq(a_in, "pixels") && !strEq(a_in, "blocks")) {
788cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitInvalidAttr(a_name, "in", a_in);
789cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
790cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // name will be "pixel-aspect-ratio-range" or
791cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "block-aspect-ratio-range".
792cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType->second[
793cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    std::string(a_in).substr(0, strlen(a_in) - 1) +
794cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    "-aspect-ratio-range"] = range;
795cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else {
796cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // For everything else (apart from "aspect-ratio"), simply append
797cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "-range" to the name for the range-type property.
798cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType->second[std::string(a_name) + "-range"] = range;
799cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
800cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // Only "quality" may have "scale".
801cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (!strEq(a_name, "quality") && a_scale != nullptr) {
802cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "scale");
803cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (strEq(a_name, "quality")) {
804cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                // The default value of "quality-scale" is "linear".
805cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType->second["quality-scale"] = a_scale == nullptr ?
806cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        "linear" : a_scale;
807cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
8086ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
809cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "quality" and "complexity" must have "default".
810cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // Other limits must not have "default".
811cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(a_name, "quality") || strEq(a_name, "complexity")) {
812cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                if (a_default == nullptr) {
813cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    return limitFoundMissingAttr(a_name, "default", false);
814cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                }
815cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                // name will be "quality-default" or "complexity-default".
816cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType->second[std::string(a_name) + "-default"] = a_default;
817cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else if (a_default != nullptr) {
818cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "default", true);
819cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
820cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
821cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    } else {
822cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_default != nullptr) {
823cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "default");
8246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
825cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_in != nullptr) {
826cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "in");
8276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
828cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_scale != nullptr) {
829cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "scale");
830cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
831cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_range != nullptr) {
832cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "range");
833cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
834cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_min != nullptr) {
835cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "min");
8366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
8376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
838cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_max != nullptr) {
839cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "max" must exist if and only if name is "channel-count" or
840cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "concurrent-instances".
841cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "min" is not ncessary.
842cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(a_name, "channel-count") ||
843cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    strEq(a_name, "concurrent-instances")) {
844cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType->second[std::string("max-") + a_name] = a_max;
845cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else {
846cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "max", false);
8476ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
848cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(a_name, "channel-count") ||
849cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                strEq(a_name, "concurrent-instances")) {
850cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "max");
8516ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
852cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
853cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_ranges != nullptr) {
854cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "ranges" must exist if and only if name is "sample-rate".
855cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(a_name, "sample-rate")) {
856cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType->second["sample-rate-ranges"] = a_ranges;
857cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else {
858cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "ranges", false);
859cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
860cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(a_name, "sample-rate")) {
861cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "ranges");
8626ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
863cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
864cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (a_value != nullptr) {
865cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "value" must exist if and only if name is "alignment" or
866cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            // "block-size".
867cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (strEq(a_name, "alignment") || strEq(a_name, "block-size")) {
868cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                mCurrentType->second[a_name] = a_value;
869cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else {
870cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return limitFoundMissingAttr(a_name, "value", false);
871cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
872cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(a_name, "alignment") || strEq(a_name, "block-size")) {
873cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return limitFoundMissingAttr(a_name, "value", false);
8746ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
875cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
8766ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
8776ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
8786ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
8796ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
8806ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
8816ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasastatus_t MediaCodecsXmlParser::addFeature(const char **attrs) {
8826ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    size_t i = 0;
883cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *name = nullptr;
8846ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    int32_t optional = -1;
8856ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    int32_t required = -1;
886cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    const char *value = nullptr;
8876ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
888cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    while (attrs[i] != nullptr) {
889cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (strEq(attrs[i], "name")) {
890cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
891cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addFeature: name is null");
892cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
8936ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            }
894cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            name = attrs[i];
895cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "optional")) {
896cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
897cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addFeature: optional is null");
898cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
899cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
900cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            optional = parseBoolean(attrs[i]) ? 1 : 0;
901cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "required")) {
902cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
903cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addFeature: required is null");
904cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
905cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
906cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            required = parseBoolean(attrs[i]) ? 1 : 0;
907cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        } else if (strEq(attrs[i], "value")) {
908cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (attrs[++i] == nullptr) {
909cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("addFeature: value is null");
910cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
911cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
912cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            value = attrs[i];
9136ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        } else {
9146ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            ALOGE("addFeature: unrecognized attribute: %s", attrs[i]);
9156ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa            return -EINVAL;
9166ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        }
9176ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ++i;
9186ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
9196ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
920cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    // Every feature must have a name.
921cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (name == nullptr) {
922cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        ALOGE("feature with no 'name' attribute");
9236ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return -EINVAL;
9246ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
9256ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
926cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
9276ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        ALOGW("ignoring null type");
9286ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa        return OK;
9296ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
930cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
931cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if ((optional != -1) || (required != -1)) {
932cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if (optional == required) {
933cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            ALOGE("feature '%s' is both/neither optional and required", name);
934cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return -EINVAL;
935cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
936cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        if ((optional == 1) || (required == 1)) {
937cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (value != nullptr) {
938cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                ALOGE("feature '%s' cannot have extra 'value'", name);
939cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                return -EINVAL;
940cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
941cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            mCurrentType->second[std::string("feature-") + name] =
942cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    optional == 1 ? "0" : "1";
943cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            return OK;
944cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
9456ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
946cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCurrentType->second[std::string("feature-") + name] = value == nullptr ?
947cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            "0" : value;
9486ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    return OK;
9496ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
9506ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
951cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconst MediaCodecsXmlParser::AttributeMap&
952cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        MediaCodecsXmlParser::getServiceAttributeMap() const {
953cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mServiceAttributeMap;
954cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
955cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
956cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconst MediaCodecsXmlParser::CodecMap&
957cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        MediaCodecsXmlParser::getCodecMap() const {
958cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mCodecMap;
9596ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
9606ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
961cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconst MediaCodecsXmlParser::RoleMap&
962cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        MediaCodecsXmlParser::getRoleMap() const {
963cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mRoleMap.empty()) {
964cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        generateRoleMap();
9656ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
966cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mRoleMap;
9676ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
9686ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
969cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasaconst char* MediaCodecsXmlParser::getCommonPrefix() const {
970cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mCommonPrefix.empty()) {
971cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        generateCommonPrefix();
972cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    }
973cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mCommonPrefix.data();
974cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
975cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
976cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasastatus_t MediaCodecsXmlParser::getParsingStatus() const {
977cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    return mParsingStatus;
978cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
979cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
980cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasavoid MediaCodecsXmlParser::generateRoleMap() const {
981cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    for (const auto& codec : mCodecMap) {
982cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const auto& codecName = codec.first;
983cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        bool isEncoder = codec.second.isEncoder;
984cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        size_t order = codec.second.order;
985cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        const auto& typeMap = codec.second.typeMap;
986cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        for (const auto& type : typeMap) {
987cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            const auto& typeName = type.first;
988cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            const char* roleName = GetComponentRole(isEncoder, typeName.data());
989fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa            if (roleName == nullptr) {
990fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa                ALOGE("Cannot find the role for %s of type %s",
991fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa                        isEncoder ? "an encoder" : "a decoder",
992fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa                        typeName.data());
993fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa                continue;
994fbe5bd5d97cdeee6f4982a7db0db42311433aacdPawin Vongmasa            }
995cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            const auto& typeAttributeMap = type.second;
996cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
997cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            auto roleIterator = mRoleMap.find(roleName);
998cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            std::multimap<size_t, NodeInfo>* nodeList;
999cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            if (roleIterator == mRoleMap.end()) {
1000cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                RoleProperties roleProperties;
1001cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                roleProperties.type = typeName;
1002cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                roleProperties.isEncoder = isEncoder;
1003cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                auto insertResult = mRoleMap.insert(
1004cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        std::make_pair(roleName, roleProperties));
1005cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                if (!insertResult.second) {
1006cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    ALOGE("Cannot add role %s", roleName);
1007cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    continue;
1008cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                }
1009cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                nodeList = &insertResult.first->second.nodeList;
1010cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            } else {
1011cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                if (roleIterator->second.type != typeName) {
1012cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    ALOGE("Role %s has mismatching types: %s and %s",
1013cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                            roleName,
1014cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                            roleIterator->second.type.data(),
1015cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                            typeName.data());
1016cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    continue;
1017cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                }
1018cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                if (roleIterator->second.isEncoder != isEncoder) {
1019cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    ALOGE("Role %s cannot be both an encoder and a decoder",
1020cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                            roleName);
1021cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    continue;
1022cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                }
1023cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                nodeList = &roleIterator->second.nodeList;
1024cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
1025cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
1026cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            NodeInfo nodeInfo;
1027cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            nodeInfo.name = codecName;
1028cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            nodeInfo.attributeList.reserve(typeAttributeMap.size());
1029cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            for (const auto& attribute : typeAttributeMap) {
1030cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                nodeInfo.attributeList.push_back(
1031cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                        Attribute{attribute.first, attribute.second});
1032cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            }
1033cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa            nodeList->insert(std::make_pair(
1034cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                    std::move(order), std::move(nodeInfo)));
1035cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        }
10366ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa    }
10376ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa}
10386ed07dc02d4240f94e7fb0786fb263bdc7a610baPawin Vongmasa
1039cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasavoid MediaCodecsXmlParser::generateCommonPrefix() const {
1040cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    if (mCodecMap.empty()) {
1041cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        return;
1042cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    }
1043cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    auto i = mCodecMap.cbegin();
1044cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    auto first = i->first.cbegin();
1045cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    auto last = i->first.cend();
1046cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    for (++i; i != mCodecMap.cend(); ++i) {
1047cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa        last = std::mismatch(
1048cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa                first, last, i->first.cbegin(), i->first.cend()).first;
1049cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    }
1050cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa    mCommonPrefix.insert(mCommonPrefix.begin(), first, last);
1051cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa}
1052cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
1053cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa} // namespace android
1054cbdeea977b79c41910b004cffcb80d81265853e8Pawin Vongmasa
1055