1ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski/* 2ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * Copyright (C) 2014 The Android Open Source Project 3ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * 4ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * you may not use this file except in compliance with the License. 6ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * You may obtain a copy of the License at 7ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * 8ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * 10ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * See the License for the specific language governing permissions and 14ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski * limitations under the License. 15ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski */ 16ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 17ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include <androidfw/ResourceTypes.h> 18ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include <utils/String8.h> 19ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 20ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski#include "AaptXml.h" 21ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 22ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskiusing namespace android; 23ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 24ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskinamespace AaptXml { 25ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 26ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, 27ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8* outError) { 28ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski Res_value value; 29ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeValue(attrIndex, &value) < 0) { 30ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 31ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "could not find attribute at index"; 32ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 33ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 34ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 35ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 36ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 37ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 38ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "attribute is not a string value"; 39ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 40ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 41ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 42ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 43ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski size_t len; 444bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski const char16_t* str = tree.getAttributeStringValue(attrIndex, &len); 45ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return str ? String8(str, len) : String8(); 46ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 47ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 48ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskistatic int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, 49ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski int32_t defValue, String8* outError) { 50ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski Res_value value; 51ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeValue(attrIndex, &value) < 0) { 52ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 53ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "could not find attribute at index"; 54ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 55ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 56ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 57ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 58ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 59ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 60ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 61ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "attribute is not an integer value"; 62ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 63ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 64ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 65ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return value.data; 66ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 67ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 68ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 69ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskissize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) { 70ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski size_t attrCount = tree.getAttributeCount(); 71ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski for (size_t i = 0; i < attrCount; i++) { 72ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeNameResID(i) == attrRes) { 73ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return (ssize_t)i; 74ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 75ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 76ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return -1; 77ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 78ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 79ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam LesinskiString8 getAttribute(const ResXMLTree& tree, const char* ns, 80ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski const char* attr, String8* outError) { 81ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = tree.indexOfAttribute(ns, attr); 82ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 83ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 84ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 85ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return getStringAttributeAtIndex(tree, idx, outError); 86ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 87ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 88ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam LesinskiString8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) { 89ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 90ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 91ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 92ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 93ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return getStringAttributeAtIndex(tree, idx, outError); 94ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 95ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 96ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam LesinskiString8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree, 97ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski uint32_t attrRes, String8* outError) { 98ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 99ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 100ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 101ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 102ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski Res_value value; 103ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 104ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType == Res_value::TYPE_STRING) { 105ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski size_t len; 1064bf58108d442b37ab4adf5ce3a4ecd63472ce254Adam Lesinski const char16_t* str = tree.getAttributeStringValue(idx, &len); 107ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return str ? String8(str, len) : String8(); 108ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 109ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski resTable.resolveReference(&value, 0); 110ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType != Res_value::TYPE_STRING) { 111ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 112ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "attribute is not a string value"; 113ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 114ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return String8(); 115ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 116ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 117ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski size_t len; 118ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski const Res_value* value2 = &value; 119ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski const char16_t* str = resTable.valueToString(value2, 0, NULL, &len); 120ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return str ? String8(str, len) : String8(); 121ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 122ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 123ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskiint32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns, 124ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski const char* attr, int32_t defValue, String8* outError) { 125ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = tree.indexOfAttribute(ns, attr); 126ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 127ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 128ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 129ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return getIntegerAttributeAtIndex(tree, idx, defValue, outError); 130ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 131ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 132ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskiint32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue, 133ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski String8* outError) { 134ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 135ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 136ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 137ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 138ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return getIntegerAttributeAtIndex(tree, idx, defValue, outError); 139ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 140ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 141ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskiint32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree, 142ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski uint32_t attrRes, int32_t defValue, String8* outError) { 143ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 144ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 145ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 146ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 147ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski Res_value value; 148ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 149ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 150ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski resTable.resolveReference(&value, 0); 151ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 152ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (value.dataType < Res_value::TYPE_FIRST_INT 153ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski || value.dataType > Res_value::TYPE_LAST_INT) { 154ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 155ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "attribute is not an integer value"; 156ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 157ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return defValue; 158ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 159ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 160ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return value.data; 161ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 162ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 163ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinskivoid getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 164ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski uint32_t attrRes, Res_value* outValue, String8* outError) { 165ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski ssize_t idx = indexOfAttribute(tree, attrRes); 166ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (idx < 0) { 167ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 168ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "attribute could not be found"; 169ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 170ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return; 171ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 172ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (tree.getAttributeValue(idx, outValue) != NO_ERROR) { 173ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outValue->dataType == Res_value::TYPE_REFERENCE) { 174ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski resTable.resolveReference(outValue, 0); 175ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 176ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski // The attribute was found and was resolved if need be. 177ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski return; 178ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 179ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski if (outError != NULL) { 180ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski *outError = "error getting resolved resource attribute"; 181ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski } 182ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} 183ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski 184ad2d07d2d98a46babb2a9472413fe9ce5080ca76Adam Lesinski} // namespace AaptXml 185