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