1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Copyright 2006 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// Build resource files from raw assets. 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceTable.h" 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 9de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski#include "AaptUtil.h" 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "XMLNode.h" 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceFilter.h" 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include "ResourceIdCache.h" 13dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "SdkConstants.h" 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 159b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski#include <algorithm> 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <androidfw/ResourceTypes.h> 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <utils/ByteOrder.h> 1882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski#include <utils/TypeHelpers.h> 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#include <stdarg.h> 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 212412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe// SSIZE: mingw does not have signed size_t == ssize_t. 222412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe// STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary. 23b12f2410c7bdbf90bd8a77b897846ee2763e3037Elliott Hughes#if !defined(_WIN32) 242412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define SSIZE(x) x 252412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define STATUST(x) x 262412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe#else 272412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define SSIZE(x) (signed size_t)x 282412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe# define STATUST(x) (status_t)x 292412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe#endif 302412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe 312412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe// Set to true for noisy debug output. 322412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampestatic const bool kIsDebug = false; 332412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe 342412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe#if PRINT_STRING_METRICS 352412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampestatic const bool kPrintStringMetrics = true; 362412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe#else 372412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampestatic const bool kPrintStringMetrics = false; 382412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe#endif 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 409b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskistatic const char* kAttrPrivateType = "^attr-private"; 419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle, 43e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<AaptAssets>& assets, 44e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const String16& resourceName, 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& target, 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* table, 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int options) 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<XMLNode> root = XMLNode::parse(target); 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (root == NULL) { 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 53a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin 54e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return compileXmlFile(bundle, assets, resourceName, root, target, table, options); 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 57e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle, 58e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<AaptAssets>& assets, 59e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const String16& resourceName, 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& target, 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& outTarget, 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* table, 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int options) 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<XMLNode> root = XMLNode::parse(target); 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (root == NULL) { 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 70e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return compileXmlFile(bundle, assets, resourceName, root, outTarget, table, options); 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 73e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t compileXmlFile(const Bundle* bundle, 74e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<AaptAssets>& assets, 75e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const String16& resourceName, 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<XMLNode>& root, 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& target, 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* table, 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int options) 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 81cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (table->versionForCompat(bundle, resourceName, target, root)) { 82cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // The file was versioned, so stop processing here. 83cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // The resource entry has already been removed and the new one added. 84cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Remove the assets entry. 85cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski sp<AaptDir> resDir = assets->getDirs().valueFor(String8("res")); 86cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski sp<AaptDir> dir = resDir->getDirs().valueFor(target->getGroupEntry().toDirName( 87cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski target->getResourceType())); 88cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski dir->removeFile(target->getPath().getPathLeaf()); 89cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return NO_ERROR; 90cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 91cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) { 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski root->removeWhitespace(true, NULL); 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) { 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski root->removeWhitespace(false, NULL); 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((options&XML_COMPILE_UTF8) != 0) { 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski root->setUTF8(true); 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 10207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (table->processBundleFormat(bundle, resourceName, target, root) != NO_ERROR) { 10307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 10407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 1055b9847ca3fbcd0bb2528dd2b4c0b789e2d501684Adam Lesinski 10607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski bool hasErrors = false; 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) { 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = root->assignResourceIds(assets, table); 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = true; 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 11407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if ((options&XML_COMPILE_PARSE_VALUES) != 0) { 11507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski status_t err = root->parseValues(assets, table); 11607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (err != NO_ERROR) { 11707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski hasErrors = true; 11807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hasErrors) { 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 125e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski if (table->modifyForCompat(bundle, resourceName, target, root) != NO_ERROR) { 126e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return UNKNOWN_ERROR; 127e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 12887332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe 1292412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 1302412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Input XML Resource:\n"); 1312412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe root->print(); 1322412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 13307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski status_t err = root->flatten(target, 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (options&XML_COMPILE_STRIP_COMMENTS) != 0, 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (options&XML_COMPILE_STRIP_RAW_VALUES) != 0); 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1402412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 1412412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Output XML Resource:\n"); 1422412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe ResXMLTree tree; 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tree.setTo(target->getData(), target->getSize()); 1442412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printXMLBlock(&tree); 1452412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski target->setCompressionMethod(ZipEntry::kCompressDeflated); 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct flag_entry 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* name; 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t nameLen; 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t value; 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* description; 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t referenceArray[] = 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e' }; 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t stringArray[] = 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 's', 't', 'r', 'i', 'n', 'g' }; 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t integerArray[] = 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'i', 'n', 't', 'e', 'g', 'e', 'r' }; 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t booleanArray[] = 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'b', 'o', 'o', 'l', 'e', 'a', 'n' }; 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t colorArray[] = 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'c', 'o', 'l', 'o', 'r' }; 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t floatArray[] = 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'f', 'l', 'o', 'a', 't' }; 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t dimensionArray[] = 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'd', 'i', 'm', 'e', 'n', 's', 'i', 'o', 'n' }; 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t fractionArray[] = 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'f', 'r', 'a', 'c', 't', 'i', 'o', 'n' }; 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t enumArray[] = 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'e', 'n', 'u', 'm' }; 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t flagsArray[] = 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 'f', 'l', 'a', 'g', 's' }; 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry gFormatFlags[] = { 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { referenceArray, sizeof(referenceArray)/2, ResTable_map::TYPE_REFERENCE, 183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a reference to another resource, in the form \"<code>@[+][<i>package</i>:]<i>type</i>:<i>name</i></code>\"\n" 184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "or to a theme attribute in the form \"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\"."}, 185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { stringArray, sizeof(stringArray)/2, ResTable_map::TYPE_STRING, 186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a string value, using '\\\\;' to escape characters such as '\\\\n' or '\\\\uxxxx' for a unicode character." }, 187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { integerArray, sizeof(integerArray)/2, ResTable_map::TYPE_INTEGER, 188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "an integer value, such as \"<code>100</code>\"." }, 189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { booleanArray, sizeof(booleanArray)/2, ResTable_map::TYPE_BOOLEAN, 190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a boolean value, either \"<code>true</code>\" or \"<code>false</code>\"." }, 191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { colorArray, sizeof(colorArray)/2, ResTable_map::TYPE_COLOR, 192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a color value, in the form of \"<code>#<i>rgb</i></code>\", \"<code>#<i>argb</i></code>\",\n" 193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\"<code>#<i>rrggbb</i></code>\", or \"<code>#<i>aarrggbb</i></code>\"." }, 194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { floatArray, sizeof(floatArray)/2, ResTable_map::TYPE_FLOAT, 195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a floating point value, such as \"<code>1.2</code>\"."}, 196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION, 197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n" 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n" 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "in (inches), mm (millimeters)." }, 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION, 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n" 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "The % suffix always means a percentage of the base size; the optional %p suffix provides a size relative to\n" 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "some parent container." }, 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { enumArray, sizeof(enumArray)/2, ResTable_map::TYPE_ENUM, NULL }, 205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { flagsArray, sizeof(flagsArray)/2, ResTable_map::TYPE_FLAGS, NULL }, 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { NULL, 0, 0, NULL } 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t suggestedArray[] = { 's', 'u', 'g', 'g', 'e', 's', 't', 'e', 'd' }; 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const flag_entry l10nRequiredFlags[] = { 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { suggestedArray, sizeof(suggestedArray)/2, ResTable_map::L10N_SUGGESTED, NULL }, 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { NULL, 0, 0, NULL } 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic const char16_t nulStr[] = { 0 }; 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic uint32_t parse_flags(const char16_t* str, size_t len, 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const flag_entry* flags, bool* outError = NULL) 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (len > 0 && isspace(*str)) { 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski str++; 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski len--; 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (len > 0 && isspace(str[len-1])) { 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski len--; 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* const end = str + len; 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t value = 0; 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (str < end) { 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* div = str; 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (div < end && *div != '|') { 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski div++; 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const flag_entry* cur = flags; 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (cur->name) { 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strzcmp16(cur->name, cur->nameLen, str, div-str) == 0) { 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value |= cur->value; 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cur++; 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!cur->name) { 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError) *outError = true; 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski str = div < end ? div+1 : div; 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outError) *outError = false; 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value; 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic String16 mayOrMust(int type, int flags) 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((type&(~flags)) == 0) { 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String16("<p>Must"); 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return String16("<p>May"); 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic void appendTypeInfo(ResourceTable* outTable, const String16& pkg, 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& typeName, const String16& ident, int type, 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const flag_entry* flags) 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hadType = false; 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (flags->name) { 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((type&flags->value) != 0 && flags->description != NULL) { 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 fullMsg(mayOrMust(type, flags->value)); 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullMsg.append(String16(" be ")); 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fullMsg.append(String16(flags->description)); 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outTable->appendTypeComment(pkg, typeName, ident, fullMsg); 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hadType = true; 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flags++; 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (hadType && (type&ResTable_map::TYPE_REFERENCE) == 0) { 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outTable->appendTypeComment(pkg, typeName, ident, 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16("<p>This may also be a reference to a resource (in the form\n" 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\"<code>@[<i>package</i>:]<i>type</i>:<i>name</i></code>\") or\n" 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "theme attribute (in the form\n" 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\"<code>?[<i>package</i>:][<i>type</i>:]<i>name</i></code>\")\n" 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "containing a value of this type.")); 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistruct PendingAttribute 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 myPackage; 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos sourcePos; 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool appendComment; 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t type; 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 ident; 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment; 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasErrors; 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool added; 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PendingAttribute(String16 _package, const sp<AaptFile>& in, 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree& block, bool _appendComment) 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski : myPackage(_package) 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , sourcePos(in->getPrintableSource(), block.getLineNumber()) 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , appendComment(_appendComment) 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , type(ResTable_map::TYPE_ANY) 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , hasErrors(false) 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , added(false) 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t createIfNeeded(ResourceTable* outTable) 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (added || hasErrors) { 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski added = true; 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 322afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if (!outTable->makeAttribute(myPackage, ident, sourcePos, type, comment, appendComment)) { 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = true; 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 326afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return NO_ERROR; 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}; 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatic status_t compileAttribute(const sp<AaptFile>& in, 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree& block, 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& myPackage, 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* outTable, 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16* outIdent = NULL, 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool inStyleable = false) 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski PendingAttribute attr(myPackage, in, block, inStyleable); 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 attr16("attr"); 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 id16("id"); 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Attribute type constants. 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 enum16("enum"); 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 flag16("flag"); 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t identIdx = block.indexOfAttribute(NULL, "name"); 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (identIdx >= 0) { 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.ident = String16(block.getAttributeStringValue(identIdx, &len)); 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outIdent) { 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outIdent = attr.ident; 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("A 'name' attribute is required for <attr>\n"); 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.comment = String16( 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t typeIdx = block.indexOfAttribute(NULL, "format"); 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx >= 0) { 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 typeStr = String16(block.getAttributeStringValue(typeIdx, &len)); 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.type = parse_flags(typeStr.string(), typeStr.size(), gFormatFlags); 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (attr.type == 0) { 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("Tag <attr> 'format' attribute value \"%s\" not valid\n", 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(typeStr).string()); 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (!inStyleable) { 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Attribute definitions outside of styleables always define the 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // attribute as a generic value. 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Attribute %s: type=0x%08x\n", String8(attr.ident).string(), attr.type); 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t minIdx = block.indexOfAttribute(NULL, "min"); 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (minIdx >= 0) { 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 val = String16(block.getAttributeStringValue(minIdx, &len)); 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::stringToInt(val.string(), val.size(), NULL)) { 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("Tag <attr> 'min' attribute must be a number, not \"%s\"\n", 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(val).string()); 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors) { 392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, 393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16(""), String16("^min"), String16(val), NULL, NULL); 394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t maxIdx = block.indexOfAttribute(NULL, "max"); 401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (maxIdx >= 0) { 402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 val = String16(block.getAttributeStringValue(maxIdx, &len)); 403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::stringToInt(val.string(), val.size(), NULL)) { 404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("Tag <attr> 'max' attribute must be a number, not \"%s\"\n", 405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(val).string()); 406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors) { 410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, 411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16(""), String16("^max"), String16(val), NULL, NULL); 412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((minIdx >= 0 || maxIdx >= 0) && (attr.type&ResTable_map::TYPE_INTEGER) == 0) { 417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("Tag <attr> must have format=integer attribute if using max or min\n"); 418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization"); 422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (l10nIdx >= 0) { 423f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert const char16_t* str = block.getAttributeStringValue(l10nIdx, &len); 424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool error; 425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error); 426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (error) { 427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.sourcePos.error("Tag <attr> 'localization' attribute value \"%s\" not valid\n", 428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(str).string()); 429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors) { 433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char buf[11]; 434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sprintf(buf, "%d", l10n_required); 435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident, 436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16(""), String16("^l10n"), String16(buf), NULL, NULL); 437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 enumOrFlagsComment; 444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::START_TAG) { 447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t localType = 0; 448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), enum16.string()) == 0) { 449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localType = ResTable_map::TYPE_ENUM; 450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), flag16.string()) == 0) { 451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski localType = ResTable_map::TYPE_FLAGS; 452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("Tag <%s> can not appear inside <attr>, only <enum> or <flag>\n", 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.createIfNeeded(outTable); 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (attr.type == ResTable_map::TYPE_ANY) { 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // No type was explicitly stated, so supplying enum tags 463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // implicitly creates an enum or flag. 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.type = 0; 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) == 0) { 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Wasn't originally specified as an enum, so update its type. 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.type |= localType; 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors) { 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char numberStr[16]; 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sprintf(numberStr, "%d", attr.type); 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski myPackage, attr16, attr.ident, String16(""), 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16("^type"), String16(numberStr), NULL, NULL, true); 476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if ((uint32_t)(attr.type&(ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)) != localType) { 481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localType == ResTable_map::TYPE_ENUM) { 482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("<enum> attribute can not be used inside a flags format\n"); 484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("<flag> attribute can not be used inside a enum format\n"); 488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 itemIdent; 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name"); 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (itemIdentIdx >= 0) { 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len)); 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("A 'name' attribute is required for <enum> or <flag>\n"); 499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 value; 503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t valueIdx = block.indexOfAttribute(NULL, "value"); 504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (valueIdx >= 0) { 505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = String16(block.getAttributeStringValue(valueIdx, &len)); 506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("A 'value' attribute is required for <enum> or <flag>\n"); 509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors && !ResTable::stringToInt(value.string(), value.size(), NULL)) { 512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("Tag <enum> or <flag> 'value' attribute must be a number," 514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " not \"%s\"\n", 515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(value).string()); 516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors) { 520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (enumOrFlagsComment.size() == 0) { 521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(mayOrMust(attr.type, 522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_map::TYPE_ENUM|ResTable_map::TYPE_FLAGS)); 523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM) 524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ? String16(" be one of the following constant values.") 525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski : String16(" be one or more (separated by '|') of the following constant values.")); 526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("</p>\n<table>\n" 527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<colgroup align=\"left\" />\n" 528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<colgroup align=\"left\" />\n" 529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<colgroup align=\"left\" />\n" 530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>")); 531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("\n<tr><td><code>")); 534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(itemIdent); 535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("</code></td><td>")); 536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(value); 537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("</td><td>")); 538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (block.getComment(&len)) { 539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16(block.getComment(&len))); 540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("</td></tr>")); 542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), 544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski myPackage, 545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr16, attr.ident, String16(""), 546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent, value, NULL, NULL, false, true); 547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr.hasErrors = true; 549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code == ResXMLTree::END_TAG) { 552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), attr16.string()) == 0) { 553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((attr.type&ResTable_map::TYPE_ENUM) != 0) { 556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), enum16.string()) != 0) { 557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("Found tag </%s> where </enum> is expected\n", 559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), flag16.string()) != 0) { 564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()) 565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .error("Found tag </%s> where </flag> is expected\n", 566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors && attr.added) { 574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski appendTypeInfo(outTable, myPackage, attr16, attr.ident, attr.type, gFormatFlags); 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!attr.hasErrors && enumOrFlagsComment.size() > 0) { 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enumOrFlagsComment.append(String16("\n</table>")); 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outTable->appendTypeComment(myPackage, attr16, attr.ident, enumOrFlagsComment); 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool localeIsDefined(const ResTable_config& config) 587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return config.locale == 0; 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddBag(Bundle* bundle, 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& in, 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree* block, 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config& config, 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& myPackage, 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& curType, 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& ident, 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& parentIdent, 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& itemIdent, 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t curFormat, 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isFormatted, 6022412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe const String16& /* product */, 603a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PseudolocalizationMethod pseudolocalize, 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool overwrite, 605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* outTable) 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 item16("item"); 609a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 str; 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<StringPool::entry_style_span> spans; 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = parseStyledString(bundle, in->getPrintableSource().string(), 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block, item16, &str, &spans, isFormatted, 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pseudolocalize); 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 6182412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe 6192412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 6202412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Adding resource bag entry l=%c%c c=%c%c orien=%d d=%d " 6212412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe " pid=%s, bag=%s, id=%s: %s\n", 6222412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.language[0], config.language[1], 6232412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.country[0], config.country[1], 6242412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.orientation, config.density, 6252412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(parentIdent).string(), 6262412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(ident).string(), 6272412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(itemIdent).string(), 6282412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(str).string()); 6292412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()), 632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski myPackage, curType, ident, parentIdent, itemIdent, str, 633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski &spans, &config, overwrite, false, curFormat); 634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns true if needle is one of the elements in the comma-separated list 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * haystack, false otherwise. 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool isInProductList(const String16& needle, const String16& haystack) { 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t *needle2 = needle.string(); 643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t *haystack2 = haystack.string(); 644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t needlesize = needle.size(); 645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (*haystack2 != '\0') { 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strncmp16(haystack2, needle2, needlesize) == 0) { 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') { 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (*haystack2 != '\0' && *haystack2 != ',') { 654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski haystack2++; 655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (*haystack2 == ',') { 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski haystack2++; 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 6648ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski/* 6658ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * A simple container that holds a resource type and name. It is ordered first by type then 6668ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * by name. 6678ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski */ 6688ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinskistruct type_ident_pair_t { 6698ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski String16 type; 6708ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski String16 ident; 6718ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 6728ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski type_ident_pair_t() { }; 6738ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { } 6748ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { } 6758ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski inline bool operator < (const type_ident_pair_t& o) const { 6768ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski int cmp = compare_type(type, o.type); 6778ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski if (cmp < 0) { 6788ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski return true; 6798ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } else if (cmp > 0) { 6808ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski return false; 6818ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } else { 6828ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski return strictly_order_type(ident, o.ident); 6838ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } 6848ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } 6858ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski}; 6868ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 6878ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t parseAndAddEntry(Bundle* bundle, 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& in, 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree* block, 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config& config, 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& myPackage, 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& curType, 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& ident, 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& curTag, 696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsStyled, 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t curFormat, 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool isFormatted, 699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& product, 700a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PseudolocalizationMethod pseudolocalize, 701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool overwrite, 7028ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski KeyedVector<type_ident_pair_t, bool>* skippedResourceNames, 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* outTable) 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err; 706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 str; 708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<StringPool::entry_style_span> spans; 709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = parseStyledString(bundle, in->getPrintableSource().string(), block, 710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag, &str, curIsStyled ? &spans : NULL, 711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski isFormatted, pseudolocalize); 712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < NO_ERROR) { 714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * If a product type was specified on the command line 719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * and also in the string, and the two are not the same, 720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * return without adding the string. 721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char *bundleProduct = bundle->getProduct(); 724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundleProduct == NULL) { 725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bundleProduct = ""; 726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (product.size() != 0) { 729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * If the command-line-specified product is empty, only "default" 731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * matches. Other variants are skipped. This is so generation 732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * of the R.java file when the product is not known is predictable. 733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundleProduct[0] == '\0') { 736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(String16("default").string(), product.string()) != 0) { 7378ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski /* 7388ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * This string has a product other than 'default'. Do not add it, 7398ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * but record it so that if we do not see the same string with 7408ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski * product 'default' or no product, then report an error. 7418ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski */ 7428ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski skippedResourceNames->replaceValueFor( 7438ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski type_ident_pair_t(curType, ident), true); 744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The command-line product is not empty. 749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * If the product for this string is on the command-line list, 750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it matches. "default" also matches, but only if nothing 751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * else has matched already. 752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 753282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (isInProductList(product, String16(bundleProduct))) { 755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ; 756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(String16("default").string(), product.string()) == 0 && 757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski !outTable->hasBagOrEntry(myPackage, curType, ident, config)) { 758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ; 759282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 763282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 764282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 7652412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 7662412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n", 7672412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.language[0], config.language[1], 7682412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.country[0], config.country[1], 7692412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.orientation, config.density, 7702412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(ident).string(), String8(str).string()); 7712412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()), 774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski myPackage, curType, ident, str, &spans, &config, 775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski false, curFormat, overwrite); 776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t compileResourceFile(Bundle* bundle, 781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptAssets>& assets, 782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<AaptFile>& in, 783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config& defParams, 784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool overwrite, 785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResourceTable* outTable) 786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree block; 788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = parseXMLResource(in, &block, false, true); 789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Top-level tag. 794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 resources16("resources"); 795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Identifier declaration tags. 797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 declare_styleable16("declare-styleable"); 798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 attr16("attr"); 799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Data creation organizational tags. 801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 string16("string"); 802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 drawable16("drawable"); 803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 color16("color"); 804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 bool16("bool"); 805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 integer16("integer"); 806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 dimen16("dimen"); 807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 fraction16("fraction"); 808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 style16("style"); 809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 plurals16("plurals"); 810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 array16("array"); 811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 string_array16("string-array"); 812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 integer_array16("integer-array"); 813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 public16("public"); 814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 public_padding16("public-padding"); 815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 private_symbols16("private-symbols"); 816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 java_symbol16("java-symbol"); 817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 add_resource16("add-resource"); 818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 skip16("skip"); 819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 eat_comment16("eat-comment"); 820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Data creation tags. 822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 bag16("bag"); 823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 item16("item"); 824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Attribute type constants. 826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 enum16("enum"); 827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // plural values 829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 other16("other"); 830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityOther16("^other"); 831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 zero16("zero"); 832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityZero16("^zero"); 833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 one16("one"); 834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityOne16("^one"); 835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 two16("two"); 836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityTwo16("^two"); 837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 few16("few"); 838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityFew16("^few"); 839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 many16("many"); 840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 quantityMany16("^many"); 841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // useful attribute names and special values 843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 name16("name"); 844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 translatable16("translatable"); 845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 formatted16("formatted"); 846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 false16("false"); 847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 myPackage(assets->getPackage()); 849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasErrors = false; 851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool fileIsTranslatable = true; 853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) { 854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fileIsTranslatable = false; 855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DefaultKeyedVector<String16, uint32_t> nextPublicId(0); 858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 8598ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // Stores the resource names that were skipped. Typically this happens when 8608ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // AAPT is invoked without a product specified and a resource has no 8618ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // 'default' product attribute. 8628ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski KeyedVector<type_ident_pair_t, bool> skippedResourceNames; 8638ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLTree::event_code_t code; 865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski do { 866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski code = block.next(); 867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } while (code == ResXMLTree::START_NAMESPACE); 868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code != ResXMLTree::START_TAG) { 871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "No start tag found\n"); 873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), resources16.string()) != 0) { 876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Invalid start tag %s\n", String8(block.getElementName(&len)).string()); 878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config curParams(defParams); 882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_config pseudoParams(curParams); 884a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoParams.language[0] = 'e'; 885a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoParams.language[1] = 'n'; 886a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoParams.country[0] = 'X'; 887a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoParams.country[1] = 'A'; 888a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin 889a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin ResTable_config pseudoBidiParams(curParams); 890a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoBidiParams.language[0] = 'a'; 891a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoBidiParams.language[1] = 'r'; 892a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoBidiParams.country[0] = 'X'; 893a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin pseudoBidiParams.country[1] = 'B'; 894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 89547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk // We should skip resources for pseudolocales if they were 89647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk // already added automatically. This is a fix for a transition period when 89747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk // manually pseudolocalized resources may be expected. 89847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk // TODO: remove this check after next SDK version release. 89947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED && 90047843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk curParams.locale == pseudoParams.locale) || 90147843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk (bundle->getPseudolocalize() & PSEUDO_BIDI && 90247843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk curParams.locale == pseudoBidiParams.locale)) { 90347843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk SourcePos(in->getPrintableSource(), 0).warning( 90447843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk "Resource file %s is skipped as pseudolocalization" 90547843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk " was done automatically.", 90647843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk in->getPrintableSource().string()); 90747843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk return NO_ERROR; 90847843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk } 90947843df11fe88b30abcac324173b6c15f16cc797Igor Viarheichyk 910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::START_TAG) { 912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16* curTag = NULL; 913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 curType; 9145892248580859620db90d5ef2e3c2f48531933faAdrian Roos String16 curName; 915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t curFormat = ResTable_map::TYPE_ANY; 916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsBag = false; 917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsBagReplaceOnOverwrite = false; 918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsStyled = false; 919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsPseudolocalizable = false; 920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool curIsFormatted = fileIsTranslatable; 921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool localHasErrors = false; 922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { 924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT 925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && code != ResXMLTree::BAD_DOCUMENT) { 926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { 928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { 935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT 936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && code != ResXMLTree::BAD_DOCUMENT) { 937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { 939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), public16.string()) == 0) { 946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); 947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 type; 949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); 950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx < 0) { 951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'type' attribute is required for <public>\n"); 952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = String16(block.getAttributeStringValue(typeIdx, &len)); 955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 name; 957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); 958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (nameIdx < 0) { 959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'name' attribute is required for <public>\n"); 960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name = String16(block.getAttributeStringValue(nameIdx, &len)); 963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t ident = 0; 965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t identIdx = block.indexOfAttribute(NULL, "id"); 966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (identIdx >= 0) { 967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* identStr = block.getAttributeStringValue(identIdx, &len); 968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value identValue; 969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::stringToInt(identStr, len, &identValue)) { 970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Given 'id' attribute is not an integer: %s\n", 971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getAttributeStringValue(identIdx, &len)).string()); 972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ident = identValue.data; 975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski nextPublicId.replaceValueFor(type, ident+1); 976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (nextPublicId.indexOfKey(type) < 0) { 978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("No 'id' attribute supplied <public>," 979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " and no previous id defined in this file.\n"); 980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (!localHasErrors) { 982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ident = nextPublicId.valueFor(type); 983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski nextPublicId.replaceValueFor(type, ident+1); 984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addPublic(srcPos, myPackage, type, name, ident); 988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < NO_ERROR) { 989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); 994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = symbols->addNestedSymbol(String8(type), srcPos); 996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->makeSymbolPublic(String8(name), srcPos); 999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment( 1000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 1001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->appendComment(String8(name), comment, srcPos); 1002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Unable to create symbols!\n"); 1004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), public16.string()) == 0) { 1011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) { 1018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); 1019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 type; 1021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); 1022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx < 0) { 1023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'type' attribute is required for <public-padding>\n"); 1024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = String16(block.getAttributeStringValue(typeIdx, &len)); 1027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 name; 1029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); 1030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (nameIdx < 0) { 1031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'name' attribute is required for <public-padding>\n"); 1032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name = String16(block.getAttributeStringValue(nameIdx, &len)); 1035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t start = 0; 1037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t startIdx = block.indexOfAttribute(NULL, "start"); 1038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (startIdx >= 0) { 1039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* startStr = block.getAttributeStringValue(startIdx, &len); 1040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value startValue; 1041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::stringToInt(startStr, len, &startValue)) { 1042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Given 'start' attribute is not an integer: %s\n", 1043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getAttributeStringValue(startIdx, &len)).string()); 1044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start = startValue.data; 1047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (nextPublicId.indexOfKey(type) < 0) { 1049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("No 'start' attribute supplied <public-padding>," 1050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " and no previous id defined in this file.\n"); 1051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (!localHasErrors) { 1053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start = nextPublicId.valueFor(type); 1054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t end = 0; 1057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t endIdx = block.indexOfAttribute(NULL, "end"); 1058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (endIdx >= 0) { 1059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* endStr = block.getAttributeStringValue(endIdx, &len); 1060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value endValue; 1061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::stringToInt(endStr, len, &endValue)) { 1062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Given 'end' attribute is not an integer: %s\n", 1063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getAttributeStringValue(endIdx, &len)).string()); 1064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski end = endValue.data; 1067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("No 'end' attribute supplied <public-padding>\n"); 1070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (end >= start) { 1074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski nextPublicId.replaceValueFor(type, end+1); 1075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Padding start '%ul' is after end '%ul'\n", 1077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start, end); 1078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment( 1082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 1083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (uint32_t curIdent=start; curIdent<=end; curIdent++) { 1084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (localHasErrors) { 1085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 curName(name); 1088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char buf[64]; 1089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sprintf(buf, "%d", (int)(end-curIdent+1)); 1090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curName.append(String16(buf)); 1091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addEntry(srcPos, myPackage, type, curName, 1093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16("padding"), NULL, &curParams, false, 1094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_map::TYPE_STRING, overwrite); 1095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < NO_ERROR) { 1096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->addPublic(srcPos, myPackage, type, 1100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curName, curIdent); 1101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < NO_ERROR) { 1102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); 1106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = symbols->addNestedSymbol(String8(type), srcPos); 1108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->makeSymbolPublic(String8(curName), srcPos); 1111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->appendComment(String8(curName), comment, srcPos); 1112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Unable to create symbols!\n"); 1114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) { 1121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) { 1128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 pkg; 1129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t pkgIdx = block.indexOfAttribute(NULL, "package"); 1130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pkgIdx < 0) { 1131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'package' attribute is required for <private-symbols>\n"); 1133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pkg = String16(block.getAttributeStringValue(pkgIdx, &len)); 1136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 113778713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).warning( 113878713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski "<private-symbols> is deprecated. Use the command line flag " 113978713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski "--private-symbols instead.\n"); 114078713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski if (assets->havePrivateSymbols()) { 114178713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).warning( 114278713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski "private symbol package already specified. Ignoring...\n"); 114378713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski } else { 114478713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski assets->setSymbolsPrivatePackage(String8(pkg)); 114578713998f94a2cc2562aa0ae7761bbc563d8eafaAdam Lesinski } 1146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) { 1151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) { 1158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); 1159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 type; 1161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); 1162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx < 0) { 1163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'type' attribute is required for <public>\n"); 1164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type = String16(block.getAttributeStringValue(typeIdx, &len)); 1167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 name; 1169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); 1170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (nameIdx < 0) { 1171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'name' attribute is required for <public>\n"); 1172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name = String16(block.getAttributeStringValue(nameIdx, &len)); 1175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptSymbols> symbols = assets->getJavaSymbolsFor(String8("R")); 1177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = symbols->addNestedSymbol(String8(type), srcPos); 1179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->makeSymbolJavaSymbol(String8(name), srcPos); 1182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment( 1183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 1184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->appendComment(String8(name), comment, srcPos); 1185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Unable to create symbols!\n"); 1187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), java_symbol16.string()) == 0) { 1193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) { 1201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); 1202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 typeName; 1204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); 1205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx < 0) { 1206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'type' attribute is required for <add-resource>\n"); 1207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeName = String16(block.getAttributeStringValue(typeIdx, &len)); 1210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 name; 1212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); 1213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (nameIdx < 0) { 1214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'name' attribute is required for <add-resource>\n"); 1215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name = String16(block.getAttributeStringValue(nameIdx, &len)); 1218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outTable->canAddEntry(srcPos, myPackage, typeName, name); 1220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) { 1224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) { 1231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); 1232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 ident; 1234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t identIdx = block.indexOfAttribute(NULL, "name"); 1235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (identIdx < 0) { 1236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("A 'name' attribute is required for <declare-styleable>\n"); 1237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ident = String16(block.getAttributeStringValue(identIdx, &len)); 1240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); 1242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 1243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = symbols->addNestedSymbol(String8("styleable"), srcPos); 1245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptSymbols> styleSymbols = symbols; 1247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = symbols->addNestedSymbol(String8(ident), srcPos); 1249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols == NULL) { 1251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski srcPos.error("Unable to create symbols!\n"); 1252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment( 1256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 1257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski styleSymbols->appendComment(String8(ident), comment, srcPos); 1258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols = NULL; 1260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { 1263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::START_TAG) { 1264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { 1265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT 1266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && code != ResXMLTree::BAD_DOCUMENT) { 1267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { 1269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { 1275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT 1276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && code != ResXMLTree::BAD_DOCUMENT) { 1277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::END_TAG) { 1278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), eat_comment16.string()) == 0) { 1279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), attr16.string()) != 0) { 1285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Tag <%s> can not appear inside <declare-styleable>, only <attr>\n", 1287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 1288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment( 1292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getComment(&len) ? block.getComment(&len) : nulStr); 1293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 itemIdent; 1294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = compileAttribute(in, block, myPackage, outTable, &itemIdent, true); 1295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (symbols != NULL) { 1300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos srcPos(String8(in->getPrintableSource()), block.getLineNumber()); 1301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->addSymbol(String8(itemIdent), 0, srcPos); 1302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski symbols->appendComment(String8(itemIdent), comment, srcPos); 1303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Attribute %s comment: %s\n", String8(itemIdent).string(), 1304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(comment).string()); 1305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code == ResXMLTree::END_TAG) { 1307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) { 1308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Found tag </%s> where </attr> is expected\n", 1313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 1314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), attr16.string()) == 0) { 1320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = compileAttribute(in, block, myPackage, outTable, NULL); 1321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = true; 1323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), item16.string()) == 0) { 1327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &item16; 1328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t attri = block.indexOfAttribute(NULL, "type"); 1329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (attri >= 0) { 1330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = String16(block.getAttributeStringValue(attri, &len)); 13315892248580859620db90d5ef2e3c2f48531933faAdrian Roos ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); 13325892248580859620db90d5ef2e3c2f48531933faAdrian Roos if (nameIdx >= 0) { 13335892248580859620db90d5ef2e3c2f48531933faAdrian Roos curName = String16(block.getAttributeStringValue(nameIdx, &len)); 13345892248580859620db90d5ef2e3c2f48531933faAdrian Roos } 1335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); 1336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (formatIdx >= 0) { 1337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 formatStr = String16(block.getAttributeStringValue( 1338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski formatIdx, &len)); 1339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = parse_flags(formatStr.string(), formatStr.size(), 1340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gFormatFlags); 1341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curFormat == 0) { 1342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Tag <item> 'format' attribute value \"%s\" not valid\n", 1344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(formatStr).string()); 1345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'type' attribute is required for <item>\n"); 1351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsStyled = true; 1354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), string16.string()) == 0) { 1355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Note the existence and locale of every string we process 135691447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath char rawLocale[RESTABLE_MAX_LOCALE_LEN]; 135791447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath curParams.getBcp47Locale(rawLocale); 1358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 locale(rawLocale); 1359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 name; 1360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 translatable; 1361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 formatted; 1362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t n = block.getAttributeCount(); 1364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i = 0; i < n; i++) { 1365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t length; 1366f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert const char16_t* attr = block.getAttributeName(i, &length); 1367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(attr, name16.string()) == 0) { 1368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski name.setTo(block.getAttributeStringValue(i, &length)); 1369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(attr, translatable16.string()) == 0) { 1370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski translatable.setTo(block.getAttributeStringValue(i, &length)); 1371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(attr, formatted16.string()) == 0) { 1372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski formatted.setTo(block.getAttributeStringValue(i, &length)); 1373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name.size() > 0) { 13775892248580859620db90d5ef2e3c2f48531933faAdrian Roos if (locale.size() == 0) { 13785892248580859620db90d5ef2e3c2f48531933faAdrian Roos outTable->addDefaultLocalization(name); 13795892248580859620db90d5ef2e3c2f48531933faAdrian Roos } 1380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (translatable == false16) { 1381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsFormatted = false; 1382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Untranslatable strings must only exist in the default [empty] locale 1383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (locale.size() > 0) { 1384a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).warning( 1385a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski "string '%s' marked untranslatable but exists in locale '%s'\n", 1386a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski String8(name).string(), 1387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski locale.string()); 1388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // hasErrors = localHasErrors = true; 1389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Intentionally empty block: 1391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // 1392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Don't add untranslatable strings to the localization table; that 1393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // way if we later see localizations of them, they'll be flagged as 1394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // having no default translation. 1395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1397a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski outTable->addLocalization( 1398a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski name, 1399a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski locale, 1400a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber())); 1401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (formatted == false16) { 1404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsFormatted = false; 1405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &string16; 1409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = string16; 1410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; 1411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsStyled = true; 141284410b054c7db0b6685a0f15cb2d1ffcb264f6c9Igor Viarheichyk curIsPseudolocalizable = fileIsTranslatable && (translatable != false16); 1413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) { 1414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &drawable16; 1415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = drawable16; 1416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR; 1417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), color16.string()) == 0) { 1418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &color16; 1419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = color16; 1420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_COLOR; 1421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), bool16.string()) == 0) { 1422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &bool16; 1423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = bool16; 1424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_BOOLEAN; 1425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), integer16.string()) == 0) { 1426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &integer16; 1427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = integer16; 1428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER; 1429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), dimen16.string()) == 0) { 1430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &dimen16; 1431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = dimen16; 1432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION; 1433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) { 1434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &fraction16; 1435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = fraction16; 1436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION; 1437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) { 1438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &bag16; 1439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t attri = block.indexOfAttribute(NULL, "type"); 1441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (attri >= 0) { 1442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = String16(block.getAttributeStringValue(attri, &len)); 1443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'type' attribute is required for <bag>\n"); 1446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), style16.string()) == 0) { 1449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &style16; 1450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = style16; 1451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), plurals16.string()) == 0) { 1453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &plurals16; 1454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = plurals16; 1455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1456a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsPseudolocalizable = fileIsTranslatable; 1457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) { 1458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &array16; 1459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = array16; 1460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBagReplaceOnOverwrite = true; 1462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); 1463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (formatIdx >= 0) { 1464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 formatStr = String16(block.getAttributeStringValue( 1465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski formatIdx, &len)); 1466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = parse_flags(formatStr.string(), formatStr.size(), 1467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski gFormatFlags); 1468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curFormat == 0) { 1469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Tag <array> 'format' attribute value \"%s\" not valid\n", 1471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(formatStr).string()); 1472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) { 1476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Check whether these strings need valid formats. 1477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // (simplified form of what string16 does above) 1478a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin bool isTranslatable = false; 1479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t n = block.getAttributeCount(); 14809a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath 14819a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath // Pseudolocalizable by default, unless this string array isn't 14829a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath // translatable. 1483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i = 0; i < n; i++) { 1484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t length; 1485f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert const char16_t* attr = block.getAttributeName(i, &length); 1486a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if (strcmp16(attr, formatted16.string()) == 0) { 1487f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert const char16_t* value = block.getAttributeStringValue(i, &length); 14889a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath if (strcmp16(value, false16.string()) == 0) { 1489a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsFormatted = false; 14909a9fa163c384e7fff159d339dfcce3b3122bece5Narayan Kamath } 1491a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } else if (strcmp16(attr, translatable16.string()) == 0) { 1492f348c15ecf78e9d58b8238ffcf1d78a279e3a862Dan Albert const char16_t* value = block.getAttributeStringValue(i, &length); 1493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(value, false16.string()) == 0) { 1494a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin isTranslatable = false; 1495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &string_array16; 1500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = array16; 1501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; 1502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBagReplaceOnOverwrite = true; 1504a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsPseudolocalizable = isTranslatable && fileIsTranslatable; 1505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) { 1506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curTag = &integer_array16; 1507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curType = array16; 1508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER; 1509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBag = true; 1510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski curIsBagReplaceOnOverwrite = true; 1511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Found tag %s where item is expected\n", 1514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string()); 1515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 ident; 1519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t identIdx = block.indexOfAttribute(NULL, "name"); 1520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (identIdx >= 0) { 1521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ident = String16(block.getAttributeStringValue(identIdx, &len)); 1522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'name' attribute is required for <%s>\n", 1525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(*curTag).string()); 1526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 product; 1530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski identIdx = block.indexOfAttribute(NULL, "product"); 1531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (identIdx >= 0) { 1532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski product = String16(block.getAttributeStringValue(identIdx, &len)); 1533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment(block.getComment(&len) ? block.getComment(&len) : nulStr); 1536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curIsBag) { 1538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Figure out the parent of this bag... 1539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 parentIdent; 1540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t parentIdentIdx = block.indexOfAttribute(NULL, "parent"); 1541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (parentIdentIdx >= 0) { 1542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski parentIdent = String16(block.getAttributeStringValue(parentIdentIdx, &len)); 1543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t sep = ident.findLast('.'); 1545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (sep >= 0) { 1546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski parentIdent.setTo(ident, sep); 1547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 1551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = outTable->startBag(SourcePos(in->getPrintableSource(), 1552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getLineNumber()), myPackage, curType, ident, 1553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski parentIdent, &curParams, 1554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski overwrite, curIsBagReplaceOnOverwrite); 1555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t elmIndex = 0; 1561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char elmIndexStr[14]; 1562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while ((code=block.next()) != ResXMLTree::END_DOCUMENT 1563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski && code != ResXMLTree::BAD_DOCUMENT) { 1564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (code == ResXMLTree::START_TAG) { 1566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), item16.string()) != 0) { 1567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Tag <%s> can not appear inside <%s>, only <item>\n", 1569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string(), 1570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(*curTag).string()); 1571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 itemIdent; 1575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curType == array16) { 1576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sprintf(elmIndexStr, "^index_%d", (int)elmIndex++); 1577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = String16(elmIndexStr); 1578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (curType == plurals16) { 1579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "quantity"); 1580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (itemIdentIdx >= 0) { 1581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 quantity16(block.getAttributeStringValue(itemIdentIdx, &len)); 1582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (quantity16 == other16) { 1583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityOther16; 1584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (quantity16 == zero16) { 1586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityZero16; 1587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (quantity16 == one16) { 1589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityOne16; 1590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (quantity16 == two16) { 1592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityTwo16; 1593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (quantity16 == few16) { 1595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityFew16; 1596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (quantity16 == many16) { 1598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = quantityMany16; 1599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else { 1601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Illegal 'quantity' attribute is <item> inside <plurals>\n"); 1603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'quantity' attribute is required for <item> inside <plurals>\n"); 1608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t itemIdentIdx = block.indexOfAttribute(NULL, "name"); 1612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (itemIdentIdx >= 0) { 1613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski itemIdent = String16(block.getAttributeStringValue(itemIdentIdx, &len)); 1614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "A 'name' attribute is required for <item>\n"); 1617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLParser::ResXMLPosition parserPosition; 1622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getPosition(&parserPosition); 1623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType, 1625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ident, parentIdent, itemIdent, curFormat, curIsFormatted, 1626a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin product, NO_PSEUDOLOCALIZATION, overwrite, outTable); 1627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err == NO_ERROR) { 1628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curIsPseudolocalizable && localeIsDefined(curParams) 1629a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin && bundle->getPseudolocalize() > 0) { 1630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // pseudolocalize here 1631a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) == 1632a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_ACCENTED) { 1633a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin block.setPosition(parserPosition); 1634a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, 1635a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curType, ident, parentIdent, itemIdent, curFormat, 1636a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsFormatted, product, PSEUDO_ACCENTED, 1637a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin overwrite, outTable); 1638a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 1639a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if ((PSEUDO_BIDI & bundle->getPseudolocalize()) == 1640a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_BIDI) { 1641a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin block.setPosition(parserPosition); 1642a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage, 1643a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curType, ident, parentIdent, itemIdent, curFormat, 1644a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsFormatted, product, PSEUDO_BIDI, 1645a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin overwrite, outTable); 1646a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 1647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1648a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 1649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (code == ResXMLTree::END_TAG) { 1653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), curTag->string()) != 0) { 1654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Found tag </%s> where </%s> is expected\n", 1656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getElementName(&len)).string(), 1657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(*curTag).string()); 1658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 1661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 1664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResXMLParser::ResXMLPosition parserPosition; 1665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski block.getPosition(&parserPosition); 1666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, 1668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *curTag, curIsStyled, curFormat, curIsFormatted, 1669a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable); 1670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? 1672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (err == NO_ERROR) { 16755892248580859620db90d5ef2e3c2f48531933faAdrian Roos if (curType == string16 && !curParams.language[0] && !curParams.country[0]) { 16765892248580859620db90d5ef2e3c2f48531933faAdrian Roos outTable->addDefaultLocalization(curName); 16775892248580859620db90d5ef2e3c2f48531933faAdrian Roos } 1678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (curIsPseudolocalizable && localeIsDefined(curParams) 1679a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin && bundle->getPseudolocalize() > 0) { 1680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // pseudolocalize here 1681a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) == 1682a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_ACCENTED) { 1683a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin block.setPosition(parserPosition); 1684a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, 1685a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin ident, *curTag, curIsStyled, curFormat, 1686a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsFormatted, product, 1687a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable); 1688a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 1689a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if ((PSEUDO_BIDI & bundle->getPseudolocalize()) == 1690a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_BIDI) { 1691a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin block.setPosition(parserPosition); 1692a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams, 1693a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin myPackage, curType, ident, *curTag, curIsStyled, curFormat, 1694a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin curIsFormatted, product, 1695a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable); 1696a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } 1697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = localHasErrors = true; 1699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0 1705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comment.size() > 0) { 1706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Comment for @%s:%s/%s: %s\n", String8(myPackage).string(), 1707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(curType).string(), String8(ident).string(), 1708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(comment).string()); 1709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 1711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!localHasErrors) { 1712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outTable->appendComment(myPackage, curType, ident, comment, false); 1713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (code == ResXMLTree::END_TAG) { 1716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (strcmp16(block.getElementName(&len), resources16.string()) != 0) { 1717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Unexpected end tag %s\n", String8(block.getElementName(&len)).string()); 1719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (code == ResXMLTree::START_NAMESPACE || code == ResXMLTree::END_NAMESPACE) { 1723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski else if (code == ResXMLTree::TEXT) { 1725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (isWhitespace(block.getText(&len))) { 1726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 1727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski SourcePos(in->getPrintableSource(), block.getLineNumber()).error( 1729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Found text \"%s\" where item tag is expected\n", 1730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(block.getText(&len)).string()); 1731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17358ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // For every resource defined, there must be exist one variant with a product attribute 17368ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // set to 'default' (or no product attribute at all). 17378ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // We check to see that for every resource that was ignored because of a mismatched 17388ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // product attribute, some product variant of that resource was processed. 17398ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski for (size_t i = 0; i < skippedResourceNames.size(); i++) { 17408ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski if (skippedResourceNames[i]) { 17418ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski const type_ident_pair_t& p = skippedResourceNames.keyAt(i); 17428ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) { 17438ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski const char* bundleProduct = 17448ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski (bundle->getProduct() == NULL) ? "" : bundle->getProduct(); 17458ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski fprintf(stderr, "In resource file %s: %s\n", 17468ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski in->getPrintableSource().string(), 17478ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski curParams.toString().string()); 17488ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 17498ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski fprintf(stderr, "\t%s '%s' does not match product %s.\n" 17508ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski "\tYou may have forgotten to include a 'default' product variant" 17518ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski " of the resource.\n", 17528ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski String8(p.type).string(), String8(p.ident).string(), 17538ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski bundleProduct[0] == 0 ? "default" : bundleProduct); 17548ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski return UNKNOWN_ERROR; 17558ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } 17568ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } 17578ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski } 17588ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski 17592412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe return hasErrors ? STATUST(UNKNOWN_ERROR) : NO_ERROR; 1760282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1761282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1762833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type) 1763833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski : mAssetsPackage(assetsPackage) 1764833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski , mPackageType(type) 1765833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski , mTypeIdOffset(0) 1766833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski , mNumLocal(0) 1767833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski , mBundle(bundle) 1768833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski{ 1769833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski ssize_t packageId = -1; 1770833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski switch (mPackageType) { 1771833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski case App: 1772833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski case AppFeature: 1773833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski packageId = 0x7f; 1774833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski break; 1775833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1776833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski case System: 1777833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski packageId = 0x01; 1778833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski break; 1779833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1780833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski case SharedLibrary: 1781833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski packageId = 0x00; 1782833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski break; 1783833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1784833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski default: 1785833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski assert(0); 1786833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski break; 1787833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 1788833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski sp<Package> package = new Package(mAssetsPackage, packageId); 1789833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski mPackages.add(assetsPackage, package); 1790833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski mOrderedPackages.add(package); 1791833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1792833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski // Every resource table always has one first entry, the bag attributes. 1793833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski const SourcePos unknown(String8("????"), 0); 1794833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski getType(mAssetsPackage, String16("attr"), unknown); 1795833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski} 1796833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1797833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinskistatic uint32_t findLargestTypeIdForPackage(const ResTable& table, const String16& packageName) { 1798833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski const size_t basePackageCount = table.getBasePackageCount(); 1799833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski for (size_t i = 0; i < basePackageCount; i++) { 1800833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (packageName == table.getBasePackageName(i)) { 1801833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return table.getLastTypeIdForPackage(i); 1802833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 1803833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 1804833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return 0; 1805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets) 1808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 1809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = assets->buildIncludedResources(bundle); 1810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 1811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 1812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mAssets = assets; 1815833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski mTypeIdOffset = findLargestTypeIdForPackage(assets->getIncludedResources(), mAssetsPackage); 1816833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1817833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski const String8& featureAfter = bundle->getFeatureAfterPackage(); 1818833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (!featureAfter.isEmpty()) { 1819833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski AssetManager featureAssetManager; 1820833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (!featureAssetManager.addAssetPath(featureAfter, NULL)) { 1821833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski fprintf(stderr, "ERROR: Feature package '%s' not found.\n", 1822833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski featureAfter.string()); 1823833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return UNKNOWN_ERROR; 1824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1826833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski const ResTable& featureTable = featureAssetManager.getResources(false); 1827030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert mTypeIdOffset = std::max(mTypeIdOffset, 1828833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski findLargestTypeIdForPackage(featureTable, mAssetsPackage)); 1829833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 1830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 1832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addPublic(const SourcePos& sourcePos, 1835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, 1836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 1837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 1838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint32_t ident) 1839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 1840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 1841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 1842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 1843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 1844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 1845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Error declaring public resource %s/%s for included package %s\n", 1846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(type).string(), String8(name).string(), 1847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(package).string()); 1848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = getType(package, type, sourcePos); 1852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 1853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return t->addPublic(sourcePos, name, ident); 1856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addEntry(const SourcePos& sourcePos, 1859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, 1860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 1861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 1862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& value, 1863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* style, 1864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* params, 1865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool doSetIndex, 1866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const int32_t format, 1867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool overwrite) 1868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 1869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 1870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 1871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 1872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 1873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 1874833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski sourcePos.error("Resource entry %s/%s is already defined in package %s.", 1875833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski String8(type).string(), String8(name).string(), String8(package).string()); 1876833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return UNKNOWN_ERROR; 1877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite, 1880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski params, doSetIndex); 1881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 1882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = e->setItem(sourcePos, value, style, format, overwrite); 1885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err == NO_ERROR) { 1886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mNumLocal++; 1887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 1889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::startBag(const SourcePos& sourcePos, 1892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, 1893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 1894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 1895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& bagParent, 1896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* params, 1897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool overlay, 18982412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe bool replace, bool /* isId */) 1899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 1900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t result = NO_ERROR; 1901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Check for adding entries in other packages... for now we do 1903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // nothing. We need to do the right thing here to support skinning. 1904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 1905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 1906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 1907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 1908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 1909833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski sourcePos.error("Resource entry %s/%s is already defined in package %s.", 1910833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski String8(type).string(), String8(name).string(), String8(package).string()); 1911833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return UNKNOWN_ERROR; 1912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1913833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 1914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) { 1915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool canAdd = false; 1916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 1917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p != NULL) { 1918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 1919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 1920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t->getCanAddEntries().indexOf(name) >= 0) { 1921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski canAdd = true; 1922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!canAdd) { 1926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n", 1927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(name).string()); 1928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params); 1932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 1933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If a parent is explicitly specified, set it. 1937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bagParent.size() > 0) { 1938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setParent(bagParent); 1939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((result = e->makeItABag(sourcePos)) != NO_ERROR) { 1942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 1943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (overlay && replace) { 1946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return e->emptyBag(sourcePos); 1947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 1949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::addBag(const SourcePos& sourcePos, 1952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, 1953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 1954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 1955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& bagParent, 1956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& bagKey, 1957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& value, 1958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* style, 1959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* params, 1960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool replace, bool isId, const int32_t format) 1961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 1962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Check for adding entries in other packages... for now we do 1963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // nothing. We need to do the right thing here to support skinning. 1964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 1965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 1966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 1967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 1968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 1969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 1970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 0 1973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (name == String16("left")) { 1974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Adding bag left: file=%s, line=%d, type=%s\n", 1975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.file.striing(), sourcePos.line, String8(type).string()); 1976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 1978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params); 1979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 1980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 1981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If a parent is explicitly specified, set it. 1984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bagParent.size() > 0) { 1985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setParent(bagParent); 1986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool first = e->getBag().indexOfKey(bagKey) < 0; 1989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = e->addToBag(sourcePos, bagKey, value, style, replace, isId, format); 1990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err == NO_ERROR && first) { 1991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mNumLocal++; 1992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 1993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 1994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 1995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 1996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package, 1997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 1998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name) const 1999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First look for this in the included resources... 2001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 2002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 2003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 2004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 2005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 2006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p != NULL) { 2011282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 2013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 2014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c != NULL) return true; 2015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& package, 2022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 2023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 2024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config& config) const 2025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First look for this in the included resources... 2027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 2028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 2029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 2030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size()); 2031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 2032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p != NULL) { 2037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 2039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 2040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c != NULL) { 2041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueFor(config); 2042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e != NULL) { 2043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasBagOrEntry(const String16& ref, 2053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16* defType, 2054282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16* defPackage) 2055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 package, type, name; 2057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::expandResourceRef(ref.string(), ref.size(), &package, &type, &name, 2058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski defType, defPackage ? defPackage:&mAssetsPackage, NULL)) { 2059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return hasBagOrEntry(package, type, name); 2062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendComment(const String16& package, 2065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 2066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 2067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& comment, 2068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool onlyIfEmpty) 2069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comment.size() <= 0) { 2071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p != NULL) { 2076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 2078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 2079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c != NULL) { 2080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c->appendComment(comment, onlyIfEmpty); 2081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::appendTypeComment(const String16& package, 2089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 2090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 2091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& comment) 2092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comment.size() <= 0) { 2094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p != NULL) { 2099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 2101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 2102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c != NULL) { 2103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c->appendTypeComment(comment); 2104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2111afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinskibool ResourceTable::makeAttribute(const String16& package, 2112afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const String16& name, 2113afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const SourcePos& source, 2114afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski int32_t format, 2115afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const String16& comment, 2116afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski bool shouldAppendComment) { 2117afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const String16 attr16("attr"); 2118afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2119afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // First look for this in the included resources... 2120afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 2121afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski .identifierForName(name.string(), name.size(), 2122afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski attr16.string(), attr16.size(), 2123afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski package.string(), package.size()); 2124afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if (rid != 0) { 2125afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski source.error("Attribute \"%s\" has already been defined", String8(name).string()); 2126afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return false; 2127afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } 2128afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2129afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski sp<ResourceTable::Entry> entry = getEntry(package, attr16, name, source, false); 2130afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if (entry == NULL) { 2131afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski source.error("Failed to create entry attr/%s", String8(name).string()); 2132afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return false; 2133afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } 2134afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2135afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if (entry->makeItABag(source) != NO_ERROR) { 2136afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return false; 2137afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } 2138afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2139afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const String16 formatKey16("^type"); 2140afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const String16 formatValue16(String8::format("%d", format)); 2141afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2142afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski ssize_t idx = entry->getBag().indexOfKey(formatKey16); 2143afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if (idx >= 0) { 2144afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // We have already set a format for this attribute, check if they are different. 2145afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // We allow duplicate attribute definitions so long as they are identical. 2146afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // This is to ensure inter-operation with libraries that define the same generic attribute. 2147afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski const Item& formatItem = entry->getBag().valueAt(idx); 2148afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski if ((format & (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) || 2149afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski formatItem.value != formatValue16) { 2150afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski source.error("Attribute \"%s\" already defined with incompatible format.\n" 2151afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski "%s:%d: Original attribute defined here.", 2152afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski String8(name).string(), formatItem.sourcePos.file.string(), 2153afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski formatItem.sourcePos.line); 2154afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return false; 2155afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } 2156afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } else { 2157afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski entry->addToBag(source, formatKey16, formatValue16); 2158afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // Increment the number of resources we have. This is used to determine if we should 2159afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski // even generate a resource table. 2160afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski mNumLocal++; 2161afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski } 2162afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski appendComment(package, attr16, name, comment, shouldAppendComment); 2163afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski return true; 2164afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski} 2165afc79be228596c56ea68c0d2fa22d0a8d733be47Adam Lesinski 2166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::canAddEntry(const SourcePos& pos, 2167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, const String16& type, const String16& name) 2168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = getType(package, type, pos); 2170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t != NULL) { 2171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski t->canAddEntry(name); 2172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::size() const { 2176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mPackages.size(); 2177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisize_t ResourceTable::numLocalResources() const { 2180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mNumLocal; 2181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::hasResources() const { 2184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mNumLocal > 0; 2185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 218727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskisp<AaptFile> ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, 218827f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski const bool isBase) 2189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8()); 219127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski status_t err = flatten(bundle, filter, data, isBase); 2192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err == NO_ERROR ? data : NULL; 2193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiinline uint32_t ResourceTable::getResId(const sp<Package>& p, 2196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const sp<Type>& t, 2197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t nameId) 2198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return makeResId(p->getAssignedId(), t->getIndex(), nameId); 2200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& package, 2203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 2204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 2205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool onlyPublic) const 2206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic); 2208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (id != 0) return id; // cache hit 2209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First look for this in the included resources... 2211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t specFlags = 0; 2212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = mAssets->getIncludedResources() 2213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .identifierForName(name.string(), name.size(), 2214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski type.string(), type.size(), 2215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski package.string(), package.size(), 2216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski &specFlags); 2217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid != 0) { 2218fa1e9d7ad0e3f5b7fce37dbdc3f5ad889274ee43Adam Lesinski if (onlyPublic && (specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) { 2219fa1e9d7ad0e3f5b7fce37dbdc3f5ad889274ee43Adam Lesinski // If this is a feature split and the resource has the same 2220fa1e9d7ad0e3f5b7fce37dbdc3f5ad889274ee43Adam Lesinski // package name as us, then everything is public. 2221fa1e9d7ad0e3f5b7fce37dbdc3f5ad889274ee43Adam Lesinski if (mPackageType != AppFeature || mAssetsPackage != package) { 2222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 2223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2226833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return ResourceIdCache::store(package, type, name, onlyPublic, rid); 2227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2229833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2230833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (p == NULL) return 0; 2231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) return 0; 22339b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 22349b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c == NULL) { 22359b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (type != String16("attr")) { 22369b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return 0; 22379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 22389b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski t = p->getTypes().valueFor(String16(kAttrPrivateType)); 22399b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (t == NULL) return 0; 22409b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski c = t->getConfigs().valueFor(name); 22419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c == NULL) return 0; 22429b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 2243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t ei = c->getEntryIndex(); 2244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ei < 0) return 0; 2245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ResourceIdCache::store(package, type, name, onlyPublic, 2247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski getResId(p, t, ei)); 2248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getResId(const String16& ref, 2251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16* defType, 2252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16* defPackage, 2253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char** outErrorMsg, 2254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool onlyPublic) const 2255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 package, type, name; 2257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool refOnlyPublic = true; 2258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!ResTable::expandResourceRef( 2259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ref.string(), ref.size(), &package, &type, &name, 2260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski defType, defPackage ? defPackage:&mAssetsPackage, 2261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outErrorMsg, &refOnlyPublic)) { 22622412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 22632412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanding resource: ref=%s\n", String8(ref).string()); 22642412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanding resource: defType=%s\n", 22652412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe defType ? String8(*defType).string() : "NULL"); 22662412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanding resource: defPackage=%s\n", 22672412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe defPackage ? String8(*defPackage).string() : "NULL"); 22682412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanding resource: ref=%s\n", String8(ref).string()); 22692412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanded resource: p=%s, t=%s, n=%s, res=0\n", 22702412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(package).string(), String8(type).string(), 22712412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(name).string()); 22722412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 2273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 2274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t res = getResId(package, type, name, onlyPublic && refOnlyPublic); 22762412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 22772412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Expanded resource: p=%s, t=%s, n=%s, res=%d\n", 22782412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(package).string(), String8(type).string(), 22792412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe String8(name).string(), res); 22802412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 2281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (res == 0) { 2282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outErrorMsg) 2283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outErrorMsg = "No resource found that matches the given name"; 2284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return res; 2286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::isValidResourceName(const String16& s) 2289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* p = s.string(); 2291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool first = true; 2292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (*p) { 2293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((*p >= 'a' && *p <= 'z') 2294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || (*p >= 'A' && *p <= 'Z') 2295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || *p == '_' 2296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || (!first && *p >= '0' && *p <= '9')) { 2297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski first = false; 2298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p++; 2299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::stringToValue(Res_value* outValue, StringPool* pool, 2307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& str, 2308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool preserveSpaces, bool coerceType, 2309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrID, 2310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* style, 2311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16* outStr, void* accessorCookie, 2312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrType, const String8* configTypeName, 2313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ConfigDescription* config) 2314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 finalStr; 2316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool res = true; 2318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (style == NULL || style->size() == 0) { 2319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Text is not styled so it can be any type... let's figure it out. 2320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res = mAssets->getIncludedResources() 2321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .stringToValue(outValue, &finalStr, str.string(), str.size(), preserveSpaces, 2322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski coerceType, attrID, NULL, &mAssetsPackage, this, 2323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski accessorCookie, attrType); 2324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Styled text can only be a string, and while collecting the style 2326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // information we have already processed that string! 2327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->size = sizeof(Res_value); 2328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->res0 = 0; 2329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->dataType = outValue->TYPE_STRING; 2330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data = 0; 2331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski finalStr = str; 2332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!res) { 2335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outValue->dataType == outValue->TYPE_STRING) { 2339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Should do better merging styles. 2340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pool) { 2341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 configStr; 2342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (config != NULL) { 2343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configStr = config->toString(); 2344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configStr = "(null)"; 2346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 23472412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 23482412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Adding to pool string style #%zu config %s: %s\n", 23492412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe style != NULL ? style->size() : 0U, 23502412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe configStr.string(), String8(finalStr).string()); 23512412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 2352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (style != NULL && style->size() > 0) { 2353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data = pool->add(finalStr, *style, configTypeName, config); 2354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data = pool->add(finalStr, true, configTypeName, config); 2356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Caller will fill this in later. 2359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data = 0; 2360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outStr) { 2363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outStr = finalStr; 2364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResource( 2372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, const String16& type, const String16& name) const 2373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getCustomResource: %s %s %s\n", String8(package).string(), 2375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(type).string(), String8(name).string()); 2376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mPackages.valueFor(package); 2377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p == NULL) return 0; 2378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(type); 2379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) return 0; 2380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getConfigs().valueFor(name); 23819b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c == NULL) { 23829b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (type != String16("attr")) { 23839b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return 0; 23849b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 23859b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski t = p->getTypes().valueFor(String16(kAttrPrivateType)); 23869b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (t == NULL) return 0; 23879b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski c = t->getConfigs().valueFor(name); 23889b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c == NULL) return 0; 23899b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 2390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t ei = c->getEntryIndex(); 2391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ei < 0) return 0; 2392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return getResId(p, t, ei); 2393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getCustomResourceWithCreation( 2396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package, const String16& type, const String16& name, 2397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool createIfNotFound) 2398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t resId = getCustomResource(package, type, name); 2400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (resId != 0 || !createIfNotFound) { 2401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return resId; 2402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2404f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski if (mAssetsPackage != package) { 2405833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski mCurrentXmlPos.error("creating resource for external package %s: %s/%s.", 2406f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski String8(package).string(), String8(type).string(), String8(name).string()); 2407833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (package == String16("android")) { 2408833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski mCurrentXmlPos.printf("did you mean to use @+id instead of @+android:id?"); 2409833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 2410833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return 0; 2411f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski } 2412f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski 2413f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski String16 value("false"); 2414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t status = addEntry(mCurrentXmlPos, package, type, name, value, NULL, NULL, true); 2415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (status == NO_ERROR) { 2416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resId = getResId(package, type, name); 2417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return resId; 2418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return 0; 2420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getRemappedPackage(uint32_t origPackage) const 2423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return origPackage; 2425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeType(uint32_t attrID, uint32_t* outType) 2428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeType #%08x\n", attrID); 2430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 2431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (getItemValue(attrID, ResTable_map::ATTR_TYPE, &value)) { 2432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeType #%08x (%s): #%08x\n", attrID, 2433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(getEntry(attrID)->getName()).string(), value.data); 2434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outType = value.data; 2435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMin(uint32_t attrID, uint32_t* outMin) 2441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeMin #%08x\n", attrID); 2443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 2444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (getItemValue(attrID, ResTable_map::ATTR_MIN, &value)) { 2445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outMin = value.data; 2446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeMax(uint32_t attrID, uint32_t* outMax) 2452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeMax #%08x\n", attrID); 2454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 2455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (getItemValue(attrID, ResTable_map::ATTR_MAX, &value)) { 2456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *outMax = value.data; 2457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiuint32_t ResourceTable::getAttributeL10N(uint32_t attrID) 2463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeL10N #%08x\n", attrID); 2465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value value; 2466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (getItemValue(attrID, ResTable_map::ATTR_L10N, &value)) { 2467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value.data; 2468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ResTable_map::L10N_NOT_REQUIRED; 2470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getLocalizationSetting() 2473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mBundle->getRequireLocalization(); 2475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::reportError(void* accessorCookie, const char* fmt, ...) 2478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (accessorCookie != NULL && fmt != NULL) { 2480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AccessorCookie* ac = (AccessorCookie*)accessorCookie; 2481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int retval=0; 2482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char buf[1024]; 2483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski va_list ap; 2484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski va_start(ap, fmt); 2485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski retval = vsnprintf(buf, sizeof(buf), fmt, ap); 2486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski va_end(ap); 2487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ac->sourcePos.error("Error: %s (at '%s' with value '%s').\n", 2488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski buf, ac->attr.string(), ac->value.string()); 2489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeKeys( 2493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrID, Vector<String16>* outKeys) 2494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<const Entry> e = getEntry(attrID); 2496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e != NULL) { 2497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = e->getBag().size(); 2498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& key = e->getBag().keyAt(i); 2500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (key.size() > 0 && key.string()[0] != '^') { 2501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outKeys->add(key); 2502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeEnum( 2510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrID, const char16_t* name, size_t nameLen, 2511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value* outValue) 2512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeEnum #%08x %s\n", attrID, String8(name, nameLen).string()); 2514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 nameStr(name, nameLen); 2515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<const Entry> e = getEntry(attrID); 2516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e != NULL) { 2517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = e->getBag().size(); 2518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 2519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Comparing %s to %s\n", String8(name, nameLen).string(), 2520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(e->getBag().keyAt(i)).string()); 2521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e->getBag().keyAt(i) == nameStr) { 2522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, outValue); 2523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getAttributeFlags( 2530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t attrID, const char16_t* name, size_t nameLen, 2531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value* outValue) 2532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->dataType = Res_value::TYPE_INT_HEX; 2534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data = 0; 2535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("getAttributeFlags #%08x %s\n", attrID, String8(name, nameLen).string()); 2537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 nameStr(name, nameLen); 2538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<const Entry> e = getEntry(attrID); 2539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e != NULL) { 2540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = e->getBag().size(); 2541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* end = name + nameLen; 2543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* pos = name; 2544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (pos < end) { 2545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char16_t* start = pos; 2546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (pos < end && *pos != '|') { 2547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pos++; 2548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 nameStr(start, pos-start); 2551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 2552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 2553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Comparing \"%s\" to \"%s\"\n", String8(nameStr).string(), 2554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(e->getBag().keyAt(i)).string()); 2555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e->getBag().keyAt(i) == nameStr) { 2556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value val; 2557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool got = getItemValue(attrID, e->getBag().valueAt(i).bagKeyId, &val); 2558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!got) { 2559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Got value: 0x%08x\n", val.data); 2562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->data |= val.data; 2563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 2564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (i >= N) { 2568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Didn't find this flag identifier. 2569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pos++; 2572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 2575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 2577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::assignResourceIds() 2580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mOrderedPackages.size(); 2582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t pi; 2583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t firstError = NO_ERROR; 2584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First generate all bag attributes and assign indices. 2586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<N; pi++) { 2587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mOrderedPackages.itemAt(pi); 2588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p == NULL || p->getTypes().size() == 0) { 2589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Empty, skip! 2590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 25939b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (mPackageType == System) { 25949b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski p->movePrivateAttrs(); 25959b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 25969b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 2597833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski // This has no sense for packages being built as AppFeature (aka with a non-zero offset). 2598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = p->applyPublicTypeOrder(); 2599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR && firstError == NO_ERROR) { 2600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski firstError = err; 2601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Generate attributes... 2604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = p->getOrderedTypes().size(); 2605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t ti; 2606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (ti=0; ti<N; ti++) { 2607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 2608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 2609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t->getOrderedConfigs().size(); 2612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<N; ci++) { 2613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); 2614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 2615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = c->getEntries().size(); 2618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 2619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueAt(ei); 2620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 2621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = e->generateAttributes(this, p->getName()); 2624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR && firstError == NO_ERROR) { 2625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski firstError = err; 2626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2631833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski uint32_t typeIdOffset = 0; 2632833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (mPackageType == AppFeature && p->getName() == mAssetsPackage) { 2633833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski typeIdOffset = mTypeIdOffset; 2634833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 2635833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 2636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos unknown(String8("????"), 0); 2637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> attr = p->getType(String16("attr"), unknown); 2638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 26394d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski // Force creation of ID if we are building feature splits. 26404d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski // Auto-generated ID resources won't apply the type ID offset correctly unless 26414d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski // the offset is applied here first. 26424d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski // b/30607637 26434d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski if (mPackageType == AppFeature && p->getName() == mAssetsPackage) { 26444d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski sp<Type> id = p->getType(String16("id"), unknown); 26454d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski } 26464d219da3c43f12ff000e685ae069374b618b30fcAdam Lesinski 2647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Assign indices... 264843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski const size_t typeCount = p->getOrderedTypes().size(); 264943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski for (size_t ti = 0; ti < typeCount; ti++) { 2650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 2651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 2652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 265443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski 2655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = t->applyPublicEntryOrder(); 2656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR && firstError == NO_ERROR) { 2657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski firstError = err; 2658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t->getOrderedConfigs().size(); 2661833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski t->setIndex(ti + 1 + typeIdOffset); 2662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t, 2664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "First type is not attr!"); 2665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 2667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ei); 2668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 2669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c->setEntryIndex(ei); 2672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 26759b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 2676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Assign resource IDs to keys in bags... 267743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski for (size_t ti = 0; ti < typeCount; ti++) { 2678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 2679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 2680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 26829b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 2683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t->getOrderedConfigs().size(); 2684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<N; ci++) { 2685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); 26869b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c == NULL) { 26879b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski continue; 26889b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 2689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Ordered config #%d: %p\n", ci, c.get()); 2690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = c->getEntries().size(); 2691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 2692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueAt(ei); 2693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 2694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = e->assignResourceIds(this, p->getName()); 2697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR && firstError == NO_ERROR) { 2698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski firstError = err; 2699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return firstError; 2705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27075892248580859620db90d5ef2e3c2f48531933faAdrian Roosstatus_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols, 27085892248580859620db90d5ef2e3c2f48531933faAdrian Roos bool skipSymbolsWithoutDefaultLocalization) { 2709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mOrderedPackages.size(); 27105892248580859620db90d5ef2e3c2f48531933faAdrian Roos const String8 defaultLocale; 27115892248580859620db90d5ef2e3c2f48531933faAdrian Roos const String16 stringType("string"); 2712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t pi; 2713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<N; pi++) { 2715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mOrderedPackages.itemAt(pi); 2716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p->getTypes().size() == 0) { 2717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Empty, skip! 2718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = p->getOrderedTypes().size(); 2722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t ti; 2723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (ti=0; ti<N; ti++) { 2725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 2726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 2727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 27299b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 2730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t->getOrderedConfigs().size(); 27319b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<AaptSymbols> typeSymbols; 27329b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (t->getName() == String16(kAttrPrivateType)) { 27339b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski typeSymbols = outSymbols->addNestedSymbol(String8("attr"), t->getPos()); 27349b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } else { 27359b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos()); 27369b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 27379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 27383fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski if (typeSymbols == NULL) { 27393fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski return UNKNOWN_ERROR; 27403fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski } 27413fb8c9b50ef1873454acf3a4e7fd33ad182c03d7Adam Lesinski 2742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<N; ci++) { 2743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); 2744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 2745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t rid = getResId(p, t, ci); 2748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (rid == 0) { 2749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 2750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2751833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) { 27525892248580859620db90d5ef2e3c2f48531933faAdrian Roos 27535892248580859620db90d5ef2e3c2f48531933faAdrian Roos if (skipSymbolsWithoutDefaultLocalization && 27545892248580859620db90d5ef2e3c2f48531933faAdrian Roos t->getName() == stringType) { 27555892248580859620db90d5ef2e3c2f48531933faAdrian Roos 27565892248580859620db90d5ef2e3c2f48531933faAdrian Roos // Don't generate symbols for strings without a default localization. 27575892248580859620db90d5ef2e3c2f48531933faAdrian Roos if (mHasDefaultLocalization.find(c->getName()) 27585892248580859620db90d5ef2e3c2f48531933faAdrian Roos == mHasDefaultLocalization.end()) { 27595892248580859620db90d5ef2e3c2f48531933faAdrian Roos // printf("Skip symbol [%08x] %s\n", rid, 27605892248580859620db90d5ef2e3c2f48531933faAdrian Roos // String8(c->getName()).string()); 27615892248580859620db90d5ef2e3c2f48531933faAdrian Roos continue; 27625892248580859620db90d5ef2e3c2f48531933faAdrian Roos } 27635892248580859620db90d5ef2e3c2f48531933faAdrian Roos } 27645892248580859620db90d5ef2e3c2f48531933faAdrian Roos 2765282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos()); 2766282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 comment(c->getComment()); 2768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeSymbols->appendComment(String8(c->getName()), comment, c->getPos()); 27698ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski //printf("Type symbol [%08x] %s comment: %s\n", rid, 27708ff15b4cada7998e78c93934ab2c869c322d7e07Adam Lesinski // String8(c->getName()).string(), String8(comment).string()); 2771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski comment = c->getTypeComment(); 2772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeSymbols->appendTypeComment(String8(c->getName()), comment); 2773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 2778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid 2782a01a9374fd386f3a8773528d7a49bc5315492dffAdam LesinskiResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src) 2783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2784a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski mLocalizations[name][locale] = src; 2785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 27875892248580859620db90d5ef2e3c2f48531933faAdrian Roosvoid 27885892248580859620db90d5ef2e3c2f48531933faAdrian RoosResourceTable::addDefaultLocalization(const String16& name) 27895892248580859620db90d5ef2e3c2f48531933faAdrian Roos{ 27905892248580859620db90d5ef2e3c2f48531933faAdrian Roos mHasDefaultLocalization.insert(name); 27915892248580859620db90d5ef2e3c2f48531933faAdrian Roos} 27925892248580859620db90d5ef2e3c2f48531933faAdrian Roos 2793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*! 2795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Flag various sorts of localization problems. '+' indicates checks already implemented; 2796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * '-' indicates checks that will be implemented in the future. 2797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 2798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized string for which no default-locale version exists => warning 2799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A string for which no version in an explicitly-requested locale exists => warning 2800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * + A localized translation of an translateable="false" string => warning 2801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * - A localized string not provided in every locale used by the table 2802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 2803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t 2804282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::validateLocalizations(void) 2805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = NO_ERROR; 2807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8 defaultLocale; 2808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For all strings... 2810030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert for (const auto& nameIter : mLocalizations) { 2811030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert const std::map<String8, SourcePos>& configSrcMap = nameIter.second; 2812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Look for strings with no default localization 2814a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (configSrcMap.count(defaultLocale) == 0) { 2815a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski SourcePos().warning("string '%s' has no default translation.", 2816030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert String8(nameIter.first).string()); 2817a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (mBundle->getVerbose()) { 2818030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert for (const auto& locale : configSrcMap) { 2819030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert locale.second.printf("locale %s found", locale.first.string()); 2820a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski } 2821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // !!! TODO: throw an error here in some circumstances 2823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Check that all requested localizations are present for this string 2826fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (mBundle->getConfigurations().size() > 0 && mBundle->getRequireLocalization()) { 2827fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const char* allConfigs = mBundle->getConfigurations().string(); 2828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* start = allConfigs; 2829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* comma; 2830030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert 2831030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert std::set<String8> missingConfigs; 2832a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski AaptLocaleValue locale; 2833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski do { 2834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 config; 2835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski comma = strchr(start, ','); 2836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comma != NULL) { 2837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.setTo(start, comma - start); 2838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski start = comma + 1; 2839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config.setTo(start); 2841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2843a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (!locale.initFromFilterString(config)) { 2844a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski continue; 2845a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski } 2846a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski 2847a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin // don't bother with the pseudolocale "en_XA" or "ar_XB" 2848a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if (config != "en_XA" && config != "ar_XB") { 2849a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (configSrcMap.find(config) == configSrcMap.end()) { 2850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // okay, no specific localization found. it's possible that we are 2851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // requiring a specific regional localization [e.g. de_DE] but there is an 2852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // available string in the generic language localization [e.g. de]; 2853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // consider that string to have fulfilled the localization requirement. 2854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 region(config.string(), 2); 2855a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (configSrcMap.find(region) == configSrcMap.end() && 2856a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski configSrcMap.count(defaultLocale) == 0) { 2857a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski missingConfigs.insert(config); 2858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2861a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski } while (comma != NULL); 2862a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski 2863a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski if (!missingConfigs.empty()) { 2864a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski String8 configStr; 2865030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert for (const auto& iter : missingConfigs) { 2866030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert configStr.appendFormat(" %s", iter.string()); 2867a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski } 2868a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski SourcePos().warning("string '%s' is missing %u required localizations:%s", 2869030f536009b56dbcc23d284541e51562bd9a6ed3Dan Albert String8(nameIter.first).string(), 2870a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski (unsigned int)missingConfigs.size(), 2871a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski configStr.string()); 2872a01a9374fd386f3a8773528d7a49bc5315492dffAdam Lesinski } 2873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 2877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 2878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 287927f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinskistatus_t ResourceTable::flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, 288027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski const sp<AaptFile>& dest, 288127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski const bool isBase) 2882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 2883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ConfigDescription nullConfig; 2884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mOrderedPackages.size(); 2886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t pi; 2887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const static String16 mipmap16("mipmap"); 2889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool useUTF8 = !bundle->getUTF16StringsOption(); 2891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2892de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski // The libraries this table references. 2893de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski Vector<sp<Package> > libraryPackages; 28946022debdbcc4498736580640c6287b57872617a2Adam Lesinski const ResTable& table = mAssets->getIncludedResources(); 28956022debdbcc4498736580640c6287b57872617a2Adam Lesinski const size_t basePackageCount = table.getBasePackageCount(); 28966022debdbcc4498736580640c6287b57872617a2Adam Lesinski for (size_t i = 0; i < basePackageCount; i++) { 28976022debdbcc4498736580640c6287b57872617a2Adam Lesinski size_t packageId = table.getBasePackageId(i); 28986022debdbcc4498736580640c6287b57872617a2Adam Lesinski String16 packageName(table.getBasePackageName(i)); 28996022debdbcc4498736580640c6287b57872617a2Adam Lesinski if (packageId > 0x01 && packageId != 0x7f && 29006022debdbcc4498736580640c6287b57872617a2Adam Lesinski packageName != String16("android")) { 29016022debdbcc4498736580640c6287b57872617a2Adam Lesinski libraryPackages.add(sp<Package>(new Package(packageName, packageId))); 29026022debdbcc4498736580640c6287b57872617a2Adam Lesinski } 29036022debdbcc4498736580640c6287b57872617a2Adam Lesinski } 2904de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 2905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Iterate through all data, collecting all values (strings, 2906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // references, etc). 2907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski StringPool valueStrings(useUTF8); 2908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<sp<Entry> > allEntries; 2909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<N; pi++) { 2910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mOrderedPackages.itemAt(pi); 2911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p->getTypes().size() == 0) { 2912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski StringPool typeStrings(useUTF8); 2916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski StringPool keyStrings(useUTF8); 2917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2918833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski ssize_t stringsAdded = 0; 2919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = p->getOrderedTypes().size(); 2920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ti=0; ti<N; ti++) { 2921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 2922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 2923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeStrings.add(String16("<empty>"), false); 2924833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski stringsAdded++; 2925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2927833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 2928833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski while (stringsAdded < t->getIndex() - 1) { 2929833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski typeStrings.add(String16("<empty>"), false); 2930833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski stringsAdded++; 2931833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 2932833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski 2933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 typeName(t->getName()); 2934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeStrings.add(typeName, false); 2935833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski stringsAdded++; 2936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is a hack to tweak the sorting order of the final strings, 2938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to put stuff that is generally not language-specific first. 2939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8 configTypeName(typeName); 2940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (configTypeName == "drawable" || configTypeName == "layout" 2941282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || configTypeName == "color" || configTypeName == "anim" 2942282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || configTypeName == "interpolator" || configTypeName == "animator" 2943282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || configTypeName == "xml" || configTypeName == "menu" 2944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || configTypeName == "mipmap" || configTypeName == "raw") { 2945282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configTypeName = "1complex"; 2946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 2947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configTypeName = "2value"; 2948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 295027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski // mipmaps don't get filtered, so they will 295127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski // allways end up in the base. Make sure they 295227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski // don't end up in a split. 295327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski if (typeName == mipmap16 && !isBase) { 295427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski continue; 295527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski } 295627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski 2957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool filterable = (typeName != mipmap16); 2958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t->getOrderedConfigs().size(); 2960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<N; ci++) { 2961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); 2962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 2963282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2964282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2965282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = c->getEntries().size(); 2966282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 2967282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ConfigDescription config = c->getEntries().keyAt(ei); 2968fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (filterable && !filter->match(config)) { 2969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueAt(ei); 2972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 2973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 2974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setNameIndex(keyStrings.add(e->getName(), true)); 2976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // If this entry has no values for other configs, 2978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // and is the default config, then it is special. Otherwise 2979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we want to add it with the config info. 2980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ConfigDescription* valueConfig = NULL; 2981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N != 1 || config == nullConfig) { 2982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski valueConfig = &config; 2983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = e->prepareFlatten(&valueStrings, this, 2986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski &configTypeName, &config); 2987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 2988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 2989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski allEntries.add(e); 2991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2992282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2993282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2994282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2995282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p->setTypeStrings(typeStrings.createStringBlock()); 2996282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p->setKeyStrings(keyStrings.createStringBlock()); 2997282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 2998282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2999282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bundle->getOutputAPKFile() != NULL) { 3000282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now we want to sort the value strings for better locality. This will 3001282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // cause the positions of the strings to change, so we need to go back 3002282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // through out resource entries and update them accordingly. Only need 3003282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // to do this if actually writing the output file. 3004282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski valueStrings.sortByConfig(); 3005282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<allEntries.size(); pi++) { 3006282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski allEntries[pi]->remapStringValue(&valueStrings); 3007282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3008282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3009282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3010282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t strAmt = 0; 3011de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3012282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Now build the array of package chunks. 3013282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<sp<AaptFile> > flatPackages; 3014282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<N; pi++) { 3015282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = mOrderedPackages.itemAt(pi); 3016282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p->getTypes().size() == 0) { 3017282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Empty, skip! 3018282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3019282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3020282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3021282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = p->getTypeStrings().size(); 3022282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3023282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t baseSize = sizeof(ResTable_package); 3024282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3025282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Start the package data. 3026282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptFile> data = new AaptFile(String8(), AaptGroupEntry(), String8()); 3027282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_package* header = (ResTable_package*)data->editData(baseSize); 3028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (header == NULL) { 3029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_package\n"); 3030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 3031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(header, 0, sizeof(*header)); 3033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.type = htods(RES_TABLE_PACKAGE_TYPE); 3034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.headerSize = htods(sizeof(*header)); 3035833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski header->id = htodl(static_cast<uint32_t>(p->getAssignedId())); 3036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strcpy16_htod(header->name, p->getName().string()); 3037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Write the string blocks. 3039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t typeStringsStart = data->getSize(); 3040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<AaptFile> strFile = p->getTypeStringsData(); 3041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t amt = data->writeData(strFile->getData(), strFile->getSize()); 30422412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kPrintStringMetrics) { 30432412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe fprintf(stderr, "**** type strings: %zd\n", SSIZE(amt)); 30442412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strAmt += amt; 3046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (amt < 0) { 3047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return amt; 3048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t keyStringsStart = data->getSize(); 3050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strFile = p->getKeyStringsData(); 3051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski amt = data->writeData(strFile->getData(), strFile->getSize()); 30522412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kPrintStringMetrics) { 30532412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe fprintf(stderr, "**** key strings: %zd\n", SSIZE(amt)); 30542412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3055282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strAmt += amt; 3056282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (amt < 0) { 3057282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return amt; 3058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 306027f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski if (isBase) { 306127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski status_t err = flattenLibraryTable(data, libraryPackages); 306227f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski if (err != NO_ERROR) { 306327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski fprintf(stderr, "ERROR: failed to write library table\n"); 306427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski return err; 306527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski } 3066de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski } 3067de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Build the type chunks inside of this package. 3069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ti=0; ti<N; ti++) { 3070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Retrieve them in the same order as the type string block. 3071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 3072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 typeName(p->getTypeStrings().stringAt(ti, &len)); 3073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getTypes().valueFor(typeName); 3074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"), 3075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Type name %s not found", 3076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(typeName).string()); 3077833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (t == NULL) { 3078833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski continue; 3079833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 3080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool filterable = (typeName != mipmap16); 308127f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski const bool skipEntireType = (typeName == mipmap16 && !isBase); 3082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0; 3084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Until a non-NO_ENTRY value has been written for a resource, 3086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // that resource is invalid; validResources[i] represents 3087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // the item at t->getOrderedConfigs().itemAt(i). 3088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<bool> validResources; 3089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski validResources.insertAt(false, 0, N); 3090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // First write the typeSpec chunk, containing information about 3092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // each resource entry in this type. 3093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 3094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t typeSpecSize = sizeof(ResTable_typeSpec) + sizeof(uint32_t)*N; 3095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t typeSpecStart = data->getSize(); 3096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_typeSpec* tsHeader = (ResTable_typeSpec*) 3097282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)data->editData(typeSpecStart+typeSpecSize)) + typeSpecStart); 3098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tsHeader == NULL) { 3099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_typeSpec\n"); 3100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 3101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(tsHeader, 0, sizeof(*tsHeader)); 3103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tsHeader->header.type = htods(RES_TABLE_TYPE_SPEC_TYPE); 3104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tsHeader->header.headerSize = htods(sizeof(*tsHeader)); 3105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tsHeader->header.size = htodl(typeSpecSize); 3106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tsHeader->id = ti+1; 3107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tsHeader->entryCount = htodl(N); 3108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t* typeSpecFlags = (uint32_t*) 3110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)data->editData()) 3111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + typeSpecStart + sizeof(ResTable_typeSpec)); 3112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(typeSpecFlags, 0, sizeof(uint32_t)*N); 3113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 3115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei); 31169b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (cl == NULL) { 31179b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski continue; 31189b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 31199b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 3120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (cl->getPublic()) { 3121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeSpecFlags[ei] |= htodl(ResTable_typeSpec::SPEC_PUBLIC); 3122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 312327f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski 312427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski if (skipEntireType) { 312527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski continue; 312627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski } 312727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski 3128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t CN = cl->getEntries().size(); 3129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<CN; ci++) { 3130fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (filterable && !filter->match(cl->getEntries().keyAt(ci))) { 3131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t cj=ci+1; cj<CN; cj++) { 3134fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (filterable && !filter->match(cl->getEntries().keyAt(cj))) { 3135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeSpecFlags[ei] |= htodl( 3138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cl->getEntries().keyAt(ci).diff(cl->getEntries().keyAt(cj))); 3139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 314427f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski if (skipEntireType) { 314527f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski continue; 314627f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski } 314727f69f4e06961fdecd1078b2292d764a157e5e1cAdam Lesinski 3148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // We need to write one type chunk for each configuration for 3149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // which we have entries in this type. 3150e97908d32ee8ea80138d085260a0eac93841c722Adam Lesinski SortedVector<ConfigDescription> uniqueConfigs; 3151e97908d32ee8ea80138d085260a0eac93841c722Adam Lesinski if (t != NULL) { 3152e97908d32ee8ea80138d085260a0eac93841c722Adam Lesinski uniqueConfigs = t->getUniqueConfigs(); 3153e97908d32ee8ea80138d085260a0eac93841c722Adam Lesinski } 3154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t typeSize = sizeof(ResTable_type) + sizeof(uint32_t)*N; 3156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3157e97908d32ee8ea80138d085260a0eac93841c722Adam Lesinski const size_t NC = uniqueConfigs.size(); 3158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ci=0; ci<NC; ci++) { 31599b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const ConfigDescription& config = uniqueConfigs[ci]; 3160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 31612412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 31622412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Writing config %zu config: imsi:%d/%d lang:%c%c cnt:%c%c " 31632412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " 31642412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe "sw%ddp w%ddp h%ddp layout:%d\n", 31652412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe ti + 1, 31662412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.mcc, config.mnc, 31672412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.language[0] ? config.language[0] : '-', 31682412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.language[1] ? config.language[1] : '-', 31692412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.country[0] ? config.country[0] : '-', 31702412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.country[1] ? config.country[1] : '-', 31712412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.orientation, 31722412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.uiMode, 31732412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.touchscreen, 31742412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.density, 31752412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.keyboard, 31762412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.inputFlags, 31772412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.navigation, 31782412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.screenWidth, 31792412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.screenHeight, 31802412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.smallestScreenWidthDp, 31812412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.screenWidthDp, 31822412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.screenHeightDp, 31832412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config.screenLayout); 31842412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3186fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (filterable && !filter->match(config)) { 3187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t typeStart = data->getSize(); 3191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_type* tHeader = (ResTable_type*) 3193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)data->editData(typeStart+typeSize)) + typeStart); 3194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tHeader == NULL) { 3195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_type\n"); 3196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_MEMORY; 3197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(tHeader, 0, sizeof(*tHeader)); 3200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->header.type = htods(RES_TABLE_TYPE_TYPE); 3201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->header.headerSize = htods(sizeof(*tHeader)); 3202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->id = ti+1; 3203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->entryCount = htodl(N); 3204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->entriesStart = htodl(typeSize); 3205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->config = config; 32062412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 32072412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("Writing type %zu config: imsi:%d/%d lang:%c%c cnt:%c%c " 32082412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " 32092412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe "sw%ddp w%ddp h%ddp layout:%d\n", 32102412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe ti + 1, 32112412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.mcc, tHeader->config.mnc, 32122412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.language[0] ? tHeader->config.language[0] : '-', 32132412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.language[1] ? tHeader->config.language[1] : '-', 32142412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.country[0] ? tHeader->config.country[0] : '-', 32152412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.country[1] ? tHeader->config.country[1] : '-', 32162412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.orientation, 32172412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.uiMode, 32182412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.touchscreen, 32192412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.density, 32202412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.keyboard, 32212412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.inputFlags, 32222412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.navigation, 32232412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.screenWidth, 32242412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.screenHeight, 32252412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.smallestScreenWidthDp, 32262412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.screenWidthDp, 32272412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.screenHeightDp, 32282412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe tHeader->config.screenLayout); 32292412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->config.swapHtoD(); 3231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Build the entries inside of this type. 3233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t ei=0; ei<N; ei++) { 3234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> cl = t->getOrderedConfigs().itemAt(ei); 32359b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<Entry> e = NULL; 32369b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (cl != NULL) { 32379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski e = cl->getEntries().valueFor(config); 32389b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 3239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Set the offset for this entry in its type. 3241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t* index = (uint32_t*) 3242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)data->editData()) 3243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski + typeStart + sizeof(ResTable_type)); 3244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e != NULL) { 3245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski index[ei] = htodl(data->getSize()-typeStart-typeSize); 3246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Create the entry. 3248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t amt = e->flatten(bundle, data, cl->getPublic()); 3249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (amt < 0) { 3250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return amt; 3251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski validResources.editItemAt(ei) = true; 3253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski index[ei] = htodl(ResTable_type::NO_ENTRY); 3255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Fill in the rest of the type information. 3259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader = (ResTable_type*) 3260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)data->editData()) + typeStart); 3261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tHeader->header.size = htodl(data->getSize()-typeStart); 3262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3264833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski // If we're building splits, then each invocation of the flattening 3265833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski // step will have 'missing' entries. Don't warn/error for this case. 3266833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (bundle->getSplitConfigurations().isEmpty()) { 3267833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski bool missing_entry = false; 3268833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ? 3269833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski "error" : "warning"; 3270833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski for (size_t i = 0; i < N; ++i) { 3271833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (!validResources[i]) { 3272833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(i); 32739b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (c != NULL) { 327401f185633c1c12017731336e7f926fe398c69781Colin Cross fprintf(stderr, "%s: no entries written for %s/%s (0x%08zx)\n", log_prefix, 32759b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski String8(typeName).string(), String8(c->getName()).string(), 32769b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski Res_MAKEID(p->getAssignedId() - 1, ti, i)); 32779b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 3278833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski missing_entry = true; 3279833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 3280833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski } 3281833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (bundle->getErrorOnMissingConfigEntry() && missing_entry) { 3282833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski fprintf(stderr, "Error: Missing entries, quit!\n"); 3283833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return NOT_ENOUGH_DATA; 3284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3285cd28bd37ea2d88dd72930f032ca73daaad5744b4Ying Wang } 3286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Fill in the rest of the package information. 3289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header = (ResTable_package*)data->editData(); 3290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.size = htodl(data->getSize()); 3291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->typeStrings = htodl(typeStringsStart); 3292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->lastPublicType = htodl(p->getTypeStrings().size()); 3293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->keyStrings = htodl(keyStringsStart); 3294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->lastPublicKey = htodl(p->getKeyStrings().size()); 3295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flatPackages.add(data); 3297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // And now write out the final chunks. 3300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t dataStart = dest->getSize(); 3301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski { 3303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // blah 3304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_header header; 3305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(&header, 0, sizeof(header)); 3306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header.header.type = htods(RES_TABLE_TYPE); 3307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header.header.headerSize = htods(sizeof(header)); 3308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header.packageCount = htodl(flatPackages.size()); 3309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = dest->writeData(&header, sizeof(header)); 3310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_header\n"); 3312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t strStart = dest->getSize(); 3317fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski status_t err = valueStrings.writeStringBlock(dest); 3318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t amt = (dest->getSize()-strStart); 3323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski strAmt += amt; 33242412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kPrintStringMetrics) { 33252412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe fprintf(stderr, "**** value strings: %zd\n", SSIZE(amt)); 33262412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe fprintf(stderr, "**** total strings: %zd\n", SSIZE(strAmt)); 33272412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3328de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pi=0; pi<flatPackages.size(); pi++) { 3330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = dest->writeData(flatPackages[pi]->getData(), 3331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski flatPackages[pi]->getSize()); 3332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating package chunk for ResTable_header\n"); 3334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_header* header = (ResTable_header*) 3339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (((uint8_t*)dest->getData()) + dataStart); 3340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header->header.size = htodl(dest->getSize() - dataStart); 3341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 33422412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kPrintStringMetrics) { 33432412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe fprintf(stderr, "**** total resource table size: %zu / %zu%% strings\n", 33442412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe dest->getSize(), (size_t)(strAmt*100)/dest->getSize()); 33452412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3350de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinskistatus_t ResourceTable::flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs) { 3351de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski // Write out the library table if necessary 3352de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski if (libs.size() > 0) { 335387332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe if (kIsDebug) { 335487332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe fprintf(stderr, "Writing library reference table\n"); 335587332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe } 3356de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3357de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski const size_t libStart = dest->getSize(); 3358de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski const size_t count = libs.size(); 33596022debdbcc4498736580640c6287b57872617a2Adam Lesinski ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange( 33606022debdbcc4498736580640c6287b57872617a2Adam Lesinski libStart, sizeof(ResTable_lib_header)); 3361de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3362de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski memset(libHeader, 0, sizeof(*libHeader)); 3363de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE); 3364de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski libHeader->header.headerSize = htods(sizeof(*libHeader)); 3365de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski libHeader->header.size = htodl(sizeof(*libHeader) + (sizeof(ResTable_lib_entry) * count)); 3366de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski libHeader->count = htodl(count); 3367de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3368de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski // Write the library entries 3369de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski for (size_t i = 0; i < count; i++) { 3370de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski const size_t entryStart = dest->getSize(); 3371de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski sp<Package> libPackage = libs[i]; 337287332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe if (kIsDebug) { 337387332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe fprintf(stderr, " Entry %s -> 0x%02x\n", 3374de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski String8(libPackage->getName()).string(), 337587332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe (uint8_t)libPackage->getAssignedId()); 337687332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe } 3377de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 33786022debdbcc4498736580640c6287b57872617a2Adam Lesinski ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange( 33796022debdbcc4498736580640c6287b57872617a2Adam Lesinski entryStart, sizeof(ResTable_lib_entry)); 3380de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski memset(entry, 0, sizeof(*entry)); 3381de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski entry->packageId = htodl(libPackage->getAssignedId()); 3382de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski strcpy16_htod(entry->packageName, libPackage->getName().string()); 3383de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski } 3384de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski } 3385de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski return NO_ERROR; 3386de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski} 3387de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski 3388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp) 3389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, 3391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<!-- This file contains <public> resource definitions for all\n" 3392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " resources that were generated from the source data. -->\n" 3393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\n" 3394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "<resources>\n"); 3395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski writePublicDefinitions(package, fp, true); 3397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski writePublicDefinitions(package, fp, false); 3398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, 3400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "\n" 3401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "</resources>\n"); 3402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::writePublicDefinitions(const String16& package, FILE* fp, bool pub) 3405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool didHeader = false; 3407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> pkg = mPackages.valueFor(package); 3409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pkg != NULL) { 3410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NT = pkg->getOrderedTypes().size(); 3411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<NT; i++) { 3412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = pkg->getOrderedTypes().itemAt(i); 3413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 3414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool didType = false; 3418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NC = t->getOrderedConfigs().size(); 3420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t j=0; j<NC; j++) { 3421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(j); 3422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 3423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c->getPublic() != pub) { 3427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski continue; 3428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!didType) { 3431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, "\n"); 3432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski didType = true; 3433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!didHeader) { 3435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pub) { 3436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp," <!-- PUBLIC SECTION. These resources have been declared public.\n"); 3437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp," Changes to these definitions will break binary compatibility. -->\n\n"); 3438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp," <!-- PRIVATE SECTION. These resources have not been declared public.\n"); 3440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp," You can make them public my moving these lines into a file in res/values. -->\n\n"); 3441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski didHeader = true; 3443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!pub) { 3445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NE = c->getEntries().size(); 3446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t k=0; k<NE; k++) { 3447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos& pos = c->getEntries().valueAt(k)->getPos(); 3448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pos.file != "") { 3449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp," <!-- Declared at %s:%d -->\n", 3450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pos.file.string(), pos.line); 3451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(fp, " <public type=\"%s\" name=\"%s\" id=\"0x%08x\" />\n", 3455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(t->getName()).string(), 3456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(c->getName()).string(), 3457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski getResId(pkg, t, c->getEntryIndex())); 3458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3463282e181b58cf72b6ca770dc7ca5f91f135444502Adam LesinskiResourceTable::Item::Item(const SourcePos& _sourcePos, 3464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool _isId, 3465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& _value, 3466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* _style, 3467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t _format) 3468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski : sourcePos(_sourcePos) 3469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , isId(_isId) 3470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , value(_value) 3471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , format(_format) 3472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , bagKeyId(0) 3473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski , evaluating(false) 3474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (_style) { 3476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski style = *_style; 3477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 348082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam LesinskiResourceTable::Entry::Entry(const Entry& entry) 348182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski : RefBase() 348282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mName(entry.mName) 348382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mParent(entry.mParent) 348482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mType(entry.mType) 348582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mItem(entry.mItem) 348682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mItemFormat(entry.mItemFormat) 348782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mBag(entry.mBag) 348882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mNameIndex(entry.mNameIndex) 348982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mParentId(entry.mParentId) 349082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski , mPos(entry.mPos) {} 349182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 3492978ab9d92934b79409638cf220de3002fea8d505Adam LesinskiResourceTable::Entry& ResourceTable::Entry::operator=(const Entry& entry) { 3493978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mName = entry.mName; 3494978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mParent = entry.mParent; 3495978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mType = entry.mType; 3496978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mItem = entry.mItem; 3497978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mItemFormat = entry.mItemFormat; 3498978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mBag = entry.mBag; 3499978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mNameIndex = entry.mNameIndex; 3500978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mParentId = entry.mParentId; 3501978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski mPos = entry.mPos; 3502978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski return *this; 3503978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski} 3504978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski 3505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos) 3506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_BAG) { 3508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_UNKNOWN) { 3511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mType = TYPE_BAG; 3512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3513282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Resource entry %s is already defined as a single item.\n" 3515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.\n", 3516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), 3517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mItem.sourcePos.file.string(), mItem.sourcePos.line); 3518282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::setItem(const SourcePos& sourcePos, 3522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& value, 3523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* style, 3524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t format, 3525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const bool overwrite) 3526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item item(sourcePos, false, value, style); 3528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_BAG) { 353043a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski if (mBag.size() == 0) { 353143a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski sourcePos.error("Resource entry %s is already defined as a bag.", 353243a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski String8(mName).string()); 353343a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski } else { 353443a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski const Item& item(mBag.valueAt(0)); 353543a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski sourcePos.error("Resource entry %s is already defined as a bag.\n" 353643a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski "%s:%d: Originally defined here.\n", 353743a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski String8(mName).string(), 353843a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski item.sourcePos.file.string(), item.sourcePos.line); 353943a0df04b0826ffb9e4589aac73b07b0c98abe8cAdam Lesinski } 3540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) { 3543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Resource entry %s is already defined.\n" 3544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.\n", 3545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), 3546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mItem.sourcePos.file.string(), mItem.sourcePos.line); 3547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mType = TYPE_ITEM; 3551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mItem = item; 3552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mItemFormat = format; 3553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos, 3557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& key, const String16& value, 3558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Vector<StringPool::entry_style_span>* style, 3559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool replace, bool isId, int32_t format) 3560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = makeItABag(sourcePos); 3562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item item(sourcePos, isId, value, style, format); 3567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // XXX NOTE: there is an error if you try to have a bag with two keys, 3569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // one an attr and one an id, with the same name. Not something we 3570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // currently ever have to worry about. 3571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ssize_t origKey = mBag.indexOfKey(key); 3572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (origKey >= 0) { 3573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!replace) { 3574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& item(mBag.valueAt(origKey)); 3575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Resource entry %s already has bag item %s.\n" 3576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.\n", 3577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), String8(key).string(), 3578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item.sourcePos.file.string(), item.sourcePos.line); 3579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Replacing %s with %s\n", 3582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(mBag.valueFor(key).value).string(), String8(value).string()); 3583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mBag.replaceValueFor(key, item); 3584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mBag.add(key, item); 3587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 359082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::Entry::removeFromBag(const String16& key) { 359182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (mType != Entry::TYPE_BAG) { 359282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski return NO_ERROR; 359382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 359482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 359582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (mBag.removeItem(key) >= 0) { 359682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski return NO_ERROR; 359782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 359882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski return UNKNOWN_ERROR; 359982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski} 360082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 3601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos) 3602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = makeItABag(sourcePos); 3604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mBag.clear(); 3609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::generateAttributes(ResourceTable* table, 3613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& package) 3614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 attr16("attr"); 3616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 id16("id"); 3617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mBag.size(); 3618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 3619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& key = mBag.keyAt(i); 3620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& it = mBag.valueAt(i); 3621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.isId) { 3622282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!table->hasBagOrEntry(key, &id16, &package)) { 3623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16 value("false"); 362487332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe if (kIsDebug) { 362587332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe fprintf(stderr, "Generating %s:id/%s\n", 362687332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe String8(package).string(), 362787332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe String8(key).string()); 362887332a7109610d02ac7f5db6af99d3a11813d5c1Andreas Gampe } 3629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = table->addEntry(SourcePos(String8("<generated>"), 0), package, 3630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski id16, key, value); 3631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (!table->hasBagOrEntry(key, &attr16, &package)) { 3636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#if 1 3638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// fprintf(stderr, "ERROR: Bag attribute '%s' has not been defined.\n", 3639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// String8(key).string()); 3640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// const Item& item(mBag.valueAt(i)); 3641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// fprintf(stderr, "Referenced from file %s line %d\n", 3642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// item.sourcePos.file.string(), item.sourcePos.line); 3643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski// return UNKNOWN_ERROR; 3644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#else 3645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char numberStr[16]; 3646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sprintf(numberStr, "%d", ResTable_map::TYPE_ANY); 3647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = table->addBag(SourcePos("<generated>", 0), package, 3648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski attr16, key, String16(""), 3649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16("^type"), 3650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String16(numberStr), NULL, NULL); 3651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski#endif 3655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::assignResourceIds(ResourceTable* table, 36612412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe const String16& /* package */) 3662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasErrors = false; 3664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_BAG) { 3666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const char* errorMsg; 3667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 style16("style"); 3668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 attr16("attr"); 3669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16 id16("id"); 3670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mParentId = 0; 3671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mParent.size() > 0) { 3672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mParentId = table->getResId(mParent, &style16, NULL, &errorMsg); 3673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mParentId == 0) { 3674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPos.error("Error retrieving parent for item: %s '%s'.\n", 3675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski errorMsg, String8(mParent).string()); 3676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = true; 3677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mBag.size(); 3680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 3681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& key = mBag.keyAt(i); 3682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item& it = mBag.editValueAt(i); 3683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.bagKeyId = table->getResId(key, 3684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.isId ? &id16 : &attr16, NULL, &errorMsg); 3685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Bag key of %s: #%08x\n", String8(key).string(), it.bagKeyId); 3686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.bagKeyId == 0) { 3687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.sourcePos.error("Error: %s: %s '%s'.\n", errorMsg, 3688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(it.isId ? id16 : attr16).string(), 3689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(key).string()); 3690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasErrors = true; 3691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 36942412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe return hasErrors ? STATUST(UNKNOWN_ERROR) : NO_ERROR; 3695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::prepareFlatten(StringPool* strings, ResourceTable* table, 3698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String8* configTypeName, const ConfigDescription* config) 3699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_ITEM) { 3701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item& it = mItem; 3702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AccessorCookie ac(it.sourcePos, String8(mName), String8(it.value)); 3703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!table->stringToValue(&it.parsedValue, strings, 3704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.value, false, true, 0, 3705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski &it.style, NULL, &ac, mItemFormat, 3706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configTypeName, config)) { 3707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (mType == TYPE_BAG) { 3710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mBag.size(); 3711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 3712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& key = mBag.keyAt(i); 3713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item& it = mBag.editValueAt(i); 3714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski AccessorCookie ac(it.sourcePos, String8(key), String8(it.value)); 3715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!table->stringToValue(&it.parsedValue, strings, 3716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.value, false, true, it.bagKeyId, 3717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski &it.style, NULL, &ac, it.format, 3718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski configTypeName, config)) { 3719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPos.error("Error: entry %s is not a single item or a bag.\n", 3724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string()); 3725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Entry::remapStringValue(StringPool* strings) 3731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mType == TYPE_ITEM) { 3733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item& it = mItem; 3734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.parsedValue.dataType == Res_value::TYPE_STRING) { 3735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data); 3736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (mType == TYPE_BAG) { 3738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mBag.size(); 3739282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 3740282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Item& it = mBag.editValueAt(i); 3741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.parsedValue.dataType == Res_value::TYPE_STRING) { 3742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.parsedValue.data = strings->mapOriginalPosToNewPos(it.parsedValue.data); 3743282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3744282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3745282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3746282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPos.error("Error: entry %s is not a single item or a bag.\n", 3747282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string()); 3748282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3749282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3750282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3751282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3752282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 37532412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampessize_t ResourceTable::Entry::flatten(Bundle* /* bundle */, const sp<AaptFile>& data, bool isPublic) 3754282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3755282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t amt = 0; 3756282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_entry header; 3757282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(&header, 0, sizeof(header)); 3758282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski header.size = htods(sizeof(header)); 37592412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe const type ty = mType; 37602412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (ty == TYPE_BAG) { 37612412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe header.flags |= htods(header.FLAG_COMPLEX); 3762282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 37632412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (isPublic) { 37642412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe header.flags |= htods(header.FLAG_PUBLIC); 37652412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 37662412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe header.key.index = htodl(mNameIndex); 3767282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ty != TYPE_BAG) { 3768282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = data->writeData(&header, sizeof(header)); 3769282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3770282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n"); 3771282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3772282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3773282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3774282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& it = mItem; 3775282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Res_value par; 3776282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memset(&par, 0, sizeof(par)); 3777282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski par.size = htods(it.parsedValue.size); 3778282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski par.dataType = it.parsedValue.dataType; 3779282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski par.res0 = it.parsedValue.res0; 3780282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski par.data = htodl(it.parsedValue.data); 3781282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski #if 0 3782282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Writing item (%s): type=%d, data=0x%x, res0=0x%x\n", 3783282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), it.parsedValue.dataType, 3784282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski it.parsedValue.data, par.res0); 3785282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski #endif 3786282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = data->writeData(&par, it.parsedValue.size); 3787282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3788282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating Res_value\n"); 3789282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3790282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3791282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski amt += it.parsedValue.size; 3792282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3793282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = mBag.size(); 3794282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 3795282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Create correct ordering of items. 3796282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski KeyedVector<uint32_t, const Item*> items; 3797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 3798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& it = mBag.valueAt(i); 3799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski items.add(it.bagKeyId, &it); 3800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = items.size(); 3802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_map_entry mapHeader; 3804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski memcpy(&mapHeader, &header, sizeof(header)); 3805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mapHeader.size = htods(sizeof(mapHeader)); 3806282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mapHeader.parent.ident = htodl(mParentId); 3807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mapHeader.count = htodl(N); 3808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = data->writeData(&mapHeader, sizeof(mapHeader)); 3809282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3810282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating ResTable_entry\n"); 3811282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3812282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3813282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3814282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 3815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& it = *items.valueAt(i); 3816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResTable_map map; 3817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski map.name.ident = htodl(it.bagKeyId); 3818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski map.value.size = htods(it.parsedValue.size); 3819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski map.value.dataType = it.parsedValue.dataType; 3820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski map.value.res0 = it.parsedValue.res0; 3821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski map.value.data = htodl(it.parsedValue.data); 3822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski err = data->writeData(&map, sizeof(map)); 3823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 3824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: out of memory creating Res_value\n"); 3825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 3826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski amt += sizeof(map); 3828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return amt; 3831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendComment(const String16& comment, 3834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool onlyIfEmpty) 3835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comment.size() <= 0) { 3837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 3838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (onlyIfEmpty && mComment.size() > 0) { 3840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 3841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mComment.size() > 0) { 3843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mComment.append(String16("\n")); 3844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mComment.append(comment); 3846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::ConfigList::appendTypeComment(const String16& comment) 3849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (comment.size() <= 0) { 3851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return; 3852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mTypeComment.size() > 0) { 3854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mTypeComment.append(String16("\n")); 3855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mTypeComment.append(comment); 3857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3859282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::addPublic(const SourcePos& sourcePos, 3860282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 3861282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const uint32_t ident) 3862282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3863282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski #if 0 3864282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t entryIdx = Res_GETENTRY(ident); 3865282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (entryIdx < 0) { 3866282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Public resource %s/%s has an invalid 0 identifier (0x%08x).\n", 3867282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), String8(name).string(), ident); 3868282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3869282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3870282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski #endif 3871282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3872282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t typeIdx = Res_GETTYPE(ident); 3873282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (typeIdx >= 0) { 3874282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeIdx++; 3875282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mPublicIndex > 0 && mPublicIndex != typeIdx) { 3876282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Public resource %s/%s has conflicting type codes for its" 3877282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " public identifiers (0x%x vs 0x%x).\n", 3878282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), String8(name).string(), 3879282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPublicIndex, typeIdx); 3880282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3881282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3882282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPublicIndex = typeIdx; 3883282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3884282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3885282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mFirstPublicSourcePos == NULL) { 3886282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mFirstPublicSourcePos = new SourcePos(sourcePos); 3887282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3888282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3889282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mPublic.indexOfKey(name) < 0) { 3890282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mPublic.add(name, Public(sourcePos, String16(), ident)); 3891282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 3892282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Public& p = mPublic.editValueFor(name); 3893282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p.ident != ident) { 3894282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Public resource %s/%s has conflicting public identifiers" 3895282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " (0x%08x vs 0x%08x).\n" 3896282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.\n", 3897282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), String8(name).string(), p.ident, ident, 3898282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p.sourcePos.file.string(), p.sourcePos.line); 3899282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 3900282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3901282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3902282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3903282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 3904282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3905282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3906282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskivoid ResourceTable::Type::canAddEntry(const String16& name) 3907282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3908282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mCanAddEntries.add(name); 3909282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3910282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3911282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry, 3912282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos& sourcePos, 3913282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* config, 3914282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool doSetIndex, 3915282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool overlay, 3916282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool autoAddOverlay) 3917282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 3918282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int pos = -1; 3919282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = mConfigs.valueFor(entry); 3920282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 3921282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) { 3922282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Resource at %s appears in overlay but not" 3923282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " in the base package; use <add-resource> to add.\n", 3924282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(entry).string()); 3925282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 3926282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3927282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c = new ConfigList(entry, sourcePos); 3928282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mConfigs.add(entry, c); 3929282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pos = (int)mOrderedConfigs.size(); 3930282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedConfigs.add(c); 3931282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (doSetIndex) { 3932282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c->setEntryIndex(pos); 3933282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3934282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3935282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3936282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ConfigDescription cdesc; 3937282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (config) cdesc = *config; 3938282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3939282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueFor(cdesc); 3940282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 39412412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 39422412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (config != NULL) { 39432412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c " 3944282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " 39452412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe "sw%ddp w%ddp h%ddp layout:%d\n", 3946282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.file.string(), sourcePos.line, 3947282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->mcc, config->mnc, 3948282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->language[0] ? config->language[0] : '-', 3949282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->language[1] ? config->language[1] : '-', 3950282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->country[0] ? config->country[0] : '-', 3951282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->country[1] ? config->country[1] : '-', 3952282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->orientation, 3953282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->touchscreen, 3954282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->density, 3955282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->keyboard, 3956282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->inputFlags, 3957282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->navigation, 3958282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->screenWidth, 3959282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->screenHeight, 3960282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->smallestScreenWidthDp, 3961282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->screenWidthDp, 3962282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski config->screenHeightDp, 39632412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe config->screenLayout); 39642412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } else { 39652412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe printf("New entry at %s:%d: NULL config\n", 39662412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe sourcePos.file.string(), sourcePos.line); 39672412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 3968282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3969282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e = new Entry(entry, sourcePos); 3970282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c->addEntry(cdesc, e); 3971282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /* 3972282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (doSetIndex) { 3973282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pos < 0) { 3974282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (pos=0; pos<(int)mOrderedConfigs.size(); pos++) { 3975282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrderedConfigs[pos] == c) { 3976282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 3977282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3978282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3979282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (pos >= (int)mOrderedConfigs.size()) { 3980282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourcePos.error("Internal error: config not found in mOrderedConfigs when adding entry"); 3981282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 3982282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3983282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3984282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setEntryIndex(pos); 3985282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3986282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 3987282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 3988282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 3989282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return e; 3990282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 3991282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 39929b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskisp<ResourceTable::ConfigList> ResourceTable::Type::removeEntry(const String16& entry) { 39939b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski ssize_t idx = mConfigs.indexOfKey(entry); 39949b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (idx < 0) { 39959b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return NULL; 39969b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 39979b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 39989b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<ConfigList> removed = mConfigs.valueAt(idx); 39999b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mConfigs.removeItemsAt(idx); 40009b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 40019b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski Vector<sp<ConfigList> >::iterator iter = std::find( 40029b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mOrderedConfigs.begin(), mOrderedConfigs.end(), removed); 40039b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (iter != mOrderedConfigs.end()) { 40049b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mOrderedConfigs.erase(iter); 40059b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 40069b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 40079b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mPublic.removeItem(entry); 40089b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return removed; 40099b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski} 40109b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 40119b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam LesinskiSortedVector<ConfigDescription> ResourceTable::Type::getUniqueConfigs() const { 40129b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski SortedVector<ConfigDescription> unique; 40139b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const size_t entryCount = mOrderedConfigs.size(); 40149b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski for (size_t i = 0; i < entryCount; i++) { 40159b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (mOrderedConfigs[i] == NULL) { 40169b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski continue; 40179b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 40189b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configs = 40199b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mOrderedConfigs[i]->getEntries(); 40209b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const size_t configCount = configs.size(); 40219b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski for (size_t j = 0; j < configCount; j++) { 40229b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski unique.add(configs.keyAt(j)); 40239b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 40249b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 40259b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return unique; 40269b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski} 40279b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 4028282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Type::applyPublicEntryOrder() 4029282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4030282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = mOrderedConfigs.size(); 4031282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<sp<ConfigList> > origOrder(mOrderedConfigs); 4032282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool hasError = false; 4033282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4034282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 4035282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 4036282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedConfigs.replaceAt(NULL, i); 4037282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4038282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4039282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t NP = mPublic.size(); 4040282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Ordering %d configs from %d public defs\n", N, NP); 4041282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t j; 4042282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (j=0; j<NP; j++) { 4043282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name = mPublic.keyAt(j); 4044282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Public& p = mPublic.valueAt(j); 4045282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t idx = Res_GETENTRY(p.ident); 4046282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Looking for entry \"%s\"/\"%s\" (0x%08x) in %d...\n", 4047282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // String8(mName).string(), String8(name).string(), p.ident, N); 4048282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool found = false; 4049282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 4050282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> e = origOrder.itemAt(i); 4051282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("#%d: \"%s\"\n", i, String8(e->getName()).string()); 4052282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e->getName() == name) { 4053282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx >= (int32_t)mOrderedConfigs.size()) { 40549b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski mOrderedConfigs.resize(idx + 1); 40559b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 40569b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 40579b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (mOrderedConfigs.itemAt(idx) == NULL) { 4058282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setPublic(true); 4059282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski e->setPublicSourcePos(p.sourcePos); 4060282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedConfigs.replaceAt(e, idx); 4061282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski origOrder.removeAt(i); 4062282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N--; 4063282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski found = true; 4064282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 4065282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 4066282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> oe = mOrderedConfigs.itemAt(idx); 4067282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4068282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p.sourcePos.error("Multiple entry names declared for public entry" 4069282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " identifier 0x%x in type %s (%s vs %s).\n" 4070282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.", 4071282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski idx+1, String8(mName).string(), 4072282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(oe->getName()).string(), 4073282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(name).string(), 4074282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski oe->getPublicSourcePos().file.string(), 4075282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski oe->getPublicSourcePos().line); 4076282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasError = true; 4077282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4078282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4079282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4080282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4081282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!found) { 4082282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p.sourcePos.error("Public symbol %s/%s declared here is not defined.", 4083282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(mName).string(), String8(name).string()); 4084282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski hasError = true; 4085282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4086282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4087282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4088282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski //printf("Copying back in %d non-public configs, have %d\n", N, origOrder.size()); 4089282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4090282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (N != origOrder.size()) { 4091282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("Internal error: remaining private symbol count mismatch\n"); 4092282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N = origOrder.size(); 4093282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4094282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4095282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski j = 0; 4096282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 40979b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung Hsieh const sp<ConfigList>& e = origOrder.itemAt(i); 4098282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // There will always be enough room for the remaining entries. 4099282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (mOrderedConfigs.itemAt(j) != NULL) { 4100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski j++; 4101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedConfigs.replaceAt(e, j); 4103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski j++; 4104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41062412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe return hasError ? STATUST(UNKNOWN_ERROR) : NO_ERROR; 4107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4109833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam LesinskiResourceTable::Package::Package(const String16& name, size_t packageId) 4110833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski : mName(name), mPackageId(packageId), 4111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mTypeStringsMapping(0xffffffff), 4112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mKeyStringsMapping(0xffffffff) 4113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::Package::getType(const String16& type, 4117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos& sourcePos, 4118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool doSetIndex) 4119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = mTypes.valueFor(type); 4121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 4122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski t = new Type(type, sourcePos); 4123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mTypes.add(type, t); 4124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedTypes.add(t); 4125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (doSetIndex) { 4126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // For some reason the type's index is set to one plus the index 4127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // in the mOrderedTypes list, rather than just the index. 4128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski t->setIndex(mOrderedTypes.size()); 4129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return t; 4132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setTypeStrings(const sp<AaptFile>& data) 4135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = setStrings(data, &mTypeStrings, &mTypeStringsMapping); 4137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 4138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Type string data is corrupt!\n"); 413957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski return err; 4140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 414157079519f4610715e4c0668c641575d10f3d4461Adam Lesinski 414257079519f4610715e4c0668c641575d10f3d4461Adam Lesinski // Retain a reference to the new data after we've successfully replaced 414357079519f4610715e4c0668c641575d10f3d4461Adam Lesinski // all uses of the old reference (in setStrings() ). 414457079519f4610715e4c0668c641575d10f3d4461Adam Lesinski mTypeStringsData = data; 414557079519f4610715e4c0668c641575d10f3d4461Adam Lesinski return NO_ERROR; 4146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setKeyStrings(const sp<AaptFile>& data) 4149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = setStrings(data, &mKeyStrings, &mKeyStringsMapping); 4151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err != NO_ERROR) { 4152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "ERROR: Key string data is corrupt!\n"); 415357079519f4610715e4c0668c641575d10f3d4461Adam Lesinski return err; 4154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 415557079519f4610715e4c0668c641575d10f3d4461Adam Lesinski 415657079519f4610715e4c0668c641575d10f3d4461Adam Lesinski // Retain a reference to the new data after we've successfully replaced 415757079519f4610715e4c0668c641575d10f3d4461Adam Lesinski // all uses of the old reference (in setStrings() ). 415857079519f4610715e4c0668c641575d10f3d4461Adam Lesinski mKeyStringsData = data; 415957079519f4610715e4c0668c641575d10f3d4461Adam Lesinski return NO_ERROR; 4160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::setStrings(const sp<AaptFile>& data, 4163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ResStringPool* strings, 4164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski DefaultKeyedVector<String16, uint32_t>* mappings) 4165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (data->getData() == NULL) { 4167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 4168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski status_t err = strings->setTo(data->getData(), data->getSize()); 4171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (err == NO_ERROR) { 4172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = strings->size(); 4173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 4174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t len; 4175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mappings->add(String16(strings->stringAt(i, &len)), i); 4176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return err; 4179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskistatus_t ResourceTable::Package::applyPublicTypeOrder() 4182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t N = mOrderedTypes.size(); 4184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Vector<sp<Type> > origOrder(mOrderedTypes); 4185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 4187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 4188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedTypes.replaceAt(NULL, i); 4189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 4192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = origOrder.itemAt(i); 4193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int32_t idx = t->getPublicIndex(); 4194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (idx > 0) { 4195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski idx--; 4196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (idx >= (int32_t)mOrderedTypes.size()) { 4197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedTypes.add(); 4198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (mOrderedTypes.itemAt(idx) != NULL) { 4200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> ot = mOrderedTypes.itemAt(idx); 4201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski t->getFirstPublicSourcePos().error("Multiple type names declared for public type" 4202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski " identifier 0x%x (%s vs %s).\n" 4203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "%s:%d: Originally defined here.", 4204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski idx, String8(ot->getName()).string(), 4205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(t->getName()).string(), 4206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ot->getFirstPublicSourcePos().file.string(), 4207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ot->getFirstPublicSourcePos().line); 4208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return UNKNOWN_ERROR; 4209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedTypes.replaceAt(t, idx); 4211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski origOrder.removeAt(i); 4212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski i--; 4213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski N--; 4214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t j=0; 4218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 42199b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung Hsieh const sp<Type>& t = origOrder.itemAt(i); 4220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // There will always be enough room for the remaining types. 4221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (mOrderedTypes.itemAt(j) != NULL) { 4222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski j++; 4223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mOrderedTypes.replaceAt(t, j); 4225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NO_ERROR; 4228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 42309b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinskivoid ResourceTable::Package::movePrivateAttrs() { 42319b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<Type> attr = mTypes.valueFor(String16("attr")); 42329b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (attr == NULL) { 42339b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Nothing to do. 42349b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return; 42359b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42369b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42379b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski Vector<sp<ConfigList> > privateAttrs; 42389b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42399b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski bool hasPublic = false; 42409b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const Vector<sp<ConfigList> >& configs = attr->getOrderedConfigs(); 42419b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const size_t configCount = configs.size(); 42429b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski for (size_t i = 0; i < configCount; i++) { 42439b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (configs[i] == NULL) { 42449b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski continue; 42459b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42469b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42479b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (attr->isPublic(configs[i]->getName())) { 42489b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski hasPublic = true; 42499b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } else { 42509b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski privateAttrs.add(configs[i]); 42519b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42529b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42539b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42549b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Only if we have public attributes do we create a separate type for 42559b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // private attributes. 42569b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski if (!hasPublic) { 42579b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski return; 42589b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42599b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42609b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Create a new type for private attributes. 42619b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<Type> privateAttrType = getType(String16(kAttrPrivateType), SourcePos()); 42629b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42639b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const size_t privateAttrCount = privateAttrs.size(); 42649b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski for (size_t i = 0; i < privateAttrCount; i++) { 42659b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const sp<ConfigList>& cl = privateAttrs[i]; 42669b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42679b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Remove the private attributes from their current type. 42689b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski attr->removeEntry(cl->getName()); 42699b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42709b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Add it to the new type. 42719b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries = cl->getEntries(); 42729b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const size_t entryCount = entries.size(); 42739b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski for (size_t j = 0; j < entryCount; j++) { 42749b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski const sp<Entry>& oldEntry = entries[j]; 42759b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski sp<Entry> entry = privateAttrType->getEntry( 42769b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski cl->getName(), oldEntry->getPos(), &entries.keyAt(j)); 42779b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski *entry = *oldEntry; 42789b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42799b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42809b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski // Move the symbols to the new type. 42819b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 42829b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski } 42839b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski} 42849b624c186cb6059dfb3ec24bfb6386a0fc17b88cAdam Lesinski 4285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Package> ResourceTable::getPackage(const String16& package) 4286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4287833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski if (package != mAssetsPackage) { 4288833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return NULL; 4289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4290833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski return mPackages.valueFor(package); 4291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Type> ResourceTable::getType(const String16& package, 4294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 4295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos& sourcePos, 4296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool doSetIndex) 4297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p = getPackage(package); 4299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p == NULL) { 4300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return p->getType(type, sourcePos, doSetIndex); 4303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package, 4306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& type, 4307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const String16& name, 4308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const SourcePos& sourcePos, 4309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool overlay, 4310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* config, 4311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool doSetIndex) 4312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = getType(package, type, sourcePos, doSetIndex); 4314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (t == NULL) { 4315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay()); 4318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4320e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskisp<ResourceTable::ConfigList> ResourceTable::getConfigList(const String16& package, 4321e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const String16& type, const String16& name) const 4322e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski{ 4323e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const size_t packageCount = mOrderedPackages.size(); 4324e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski for (size_t pi = 0; pi < packageCount; pi++) { 4325e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<Package>& p = mOrderedPackages[pi]; 4326e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski if (p == NULL || p->getName() != package) { 4327e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski continue; 4328e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4329e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4330e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const Vector<sp<Type> >& types = p->getOrderedTypes(); 4331e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const size_t typeCount = types.size(); 4332e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski for (size_t ti = 0; ti < typeCount; ti++) { 4333e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<Type>& t = types[ti]; 4334e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski if (t == NULL || t->getName() != type) { 4335e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski continue; 4336e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4337e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4338e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const Vector<sp<ConfigList> >& configs = t->getOrderedConfigs(); 4339e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const size_t configCount = configs.size(); 4340e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski for (size_t ci = 0; ci < configCount; ci++) { 4341e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<ConfigList>& cl = configs[ci]; 4342e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski if (cl == NULL || cl->getName() != name) { 4343e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski continue; 4344e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4345e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4346e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return cl; 4347e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4348e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4349e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4350e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NULL; 4351e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski} 4352e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskisp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID, 4354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const ResTable_config* config) const 4355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4356833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski size_t pid = Res_GETPACKAGE(resID)+1; 4357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = mOrderedPackages.size(); 4358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> p; 4359833f3ccbc8f4dd1ec8abb9121988b99ff34ec4c1Adam Lesinski for (size_t i = 0; i < N; i++) { 4360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Package> check = mOrderedPackages[i]; 4361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (check->getAssignedId() == pid) { 4362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski p = check; 4363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 4364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (p == NULL) { 4368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Package not found for resource #%08x\n", resID); 4369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int tid = Res_GETTYPE(resID); 4373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) { 4374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Type not found for resource #%08x\n", resID); 4375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Type> t = p->getOrderedTypes()[tid]; 4378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int eid = Res_GETENTRY(resID); 4380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) { 4381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID); 4382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<ConfigList> c = t->getOrderedConfigs()[eid]; 4386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 4387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID); 4388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ConfigDescription cdesc; 4392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (config) cdesc = *config; 4393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<Entry> e = c->getEntries().valueFor(cdesc); 4394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (c == NULL) { 4395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID); 4396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return e; 4400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiconst ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrID) const 4403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<const Entry> e = getEntry(resID); 4405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (e == NULL) { 4406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = e->getBag().size(); 4410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (size_t i=0; i<N; i++) { 4411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item& it = e->getBag().valueAt(i); 4412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.bagKeyId == 0) { 4413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n", 4414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(e->getName()).string(), 4415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(e->getBag().keyAt(i)).string()); 4416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (it.bagKeyId == attrID) { 4418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ⁢ 4419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return NULL; 4423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 4424282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskibool ResourceTable::getItemValue( 4426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski uint32_t resID, uint32_t attrID, Res_value* outValue) 4427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski{ 4428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const Item* item = getItem(resID, attrID); 4429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 4430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bool res = false; 4431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (item != NULL) { 4432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (item->evaluating) { 4433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sp<const Entry> e = getEntry(resID); 4434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski const size_t N = e->getBag().size(); 4435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski size_t i; 4436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (i=0; i<N; i++) { 4437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (&e->getBag().valueAt(i) == item) { 4438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 4439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n", 4442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(e->getName()).string(), 4443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String8(e->getBag().keyAt(i)).string()); 4444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 4445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item->evaluating = true; 4447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski res = stringToValue(outValue, NULL, item->value, false, false, item->bagKeyId); 44482412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe if (kIsDebug) { 4449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (res) { 4450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("getItemValue of #%08x[#%08x] (%s): type=#%08x, data=#%08x\n", 4451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resID, attrID, String8(getEntry(resID)->getName()).string(), 4452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue->dataType, outValue->data); 4453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 4454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski printf("getItemValue of #%08x[#%08x]: failed\n", 4455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski resID, attrID); 4456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 44572412f84064c26b643c722ce914a97c4ec7776c69Andreas Gampe } 4458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski item->evaluating = false; 4459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 4460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return res; 4461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 446282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 446382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/** 446428994d8d181c286b39811441ce78399576c2d315Adam Lesinski * Returns the SDK version at which the attribute was 446528994d8d181c286b39811441ce78399576c2d315Adam Lesinski * made public, or -1 if the resource ID is not an attribute 446628994d8d181c286b39811441ce78399576c2d315Adam Lesinski * or is not public. 446782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */ 446828994d8d181c286b39811441ce78399576c2d315Adam Lesinskiint ResourceTable::getPublicAttributeSdkLevel(uint32_t attrId) const { 446928994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (Res_GETPACKAGE(attrId) + 1 != 0x01 || Res_GETTYPE(attrId) + 1 != 0x01) { 447028994d8d181c286b39811441ce78399576c2d315Adam Lesinski return -1; 447182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 447282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 447382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski uint32_t specFlags; 447482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (!mAssets->getIncludedResources().getResourceFlags(attrId, &specFlags)) { 447528994d8d181c286b39811441ce78399576c2d315Adam Lesinski return -1; 447628994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 447728994d8d181c286b39811441ce78399576c2d315Adam Lesinski 447828994d8d181c286b39811441ce78399576c2d315Adam Lesinski if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) { 447928994d8d181c286b39811441ce78399576c2d315Adam Lesinski return -1; 448028994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 448128994d8d181c286b39811441ce78399576c2d315Adam Lesinski 448228994d8d181c286b39811441ce78399576c2d315Adam Lesinski const size_t entryId = Res_GETENTRY(attrId); 448328994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (entryId <= 0x021c) { 448428994d8d181c286b39811441ce78399576c2d315Adam Lesinski return 1; 448528994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x021d) { 448628994d8d181c286b39811441ce78399576c2d315Adam Lesinski return 2; 448728994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x0269) { 448828994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_CUPCAKE; 448928994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x028d) { 449028994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_DONUT; 449128994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x02ad) { 449228994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_ECLAIR; 449328994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x02b3) { 449428994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_ECLAIR_0_1; 449528994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x02b5) { 449628994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_ECLAIR_MR1; 449728994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x02bd) { 449828994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_FROYO; 449928994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x02cb) { 450028994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_GINGERBREAD; 450128994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x0361) { 450228994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_HONEYCOMB; 450328994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x0366) { 450428994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_HONEYCOMB_MR1; 450528994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03a6) { 450628994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_HONEYCOMB_MR2; 450728994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03ae) { 450828994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_JELLY_BEAN; 450928994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03cc) { 451028994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_JELLY_BEAN_MR1; 451128994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03da) { 451228994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_JELLY_BEAN_MR2; 451328994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03f1) { 451428994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_KITKAT; 451528994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x03f6) { 451628994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_KITKAT_WATCH; 451728994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (entryId <= 0x04ce) { 451828994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_LOLLIPOP; 451928994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else { 452028994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Anything else is marked as defined in 452128994d8d181c286b39811441ce78399576c2d315Adam Lesinski // SDK_LOLLIPOP_MR1 since after this 452228994d8d181c286b39811441ce78399576c2d315Adam Lesinski // version no attribute compat work 452328994d8d181c286b39811441ce78399576c2d315Adam Lesinski // needs to be done. 452428994d8d181c286b39811441ce78399576c2d315Adam Lesinski return SDK_LOLLIPOP_MR1; 452582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 452682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski} 452782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 452828994d8d181c286b39811441ce78399576c2d315Adam Lesinski/** 452928994d8d181c286b39811441ce78399576c2d315Adam Lesinski * First check the Manifest, then check the command line flag. 453028994d8d181c286b39811441ce78399576c2d315Adam Lesinski */ 453128994d8d181c286b39811441ce78399576c2d315Adam Lesinskistatic int getMinSdkVersion(const Bundle* bundle) { 453228994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (bundle->getManifestMinSdkVersion() != NULL && strlen(bundle->getManifestMinSdkVersion()) > 0) { 453328994d8d181c286b39811441ce78399576c2d315Adam Lesinski return atoi(bundle->getManifestMinSdkVersion()); 453428994d8d181c286b39811441ce78399576c2d315Adam Lesinski } else if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) { 453528994d8d181c286b39811441ce78399576c2d315Adam Lesinski return atoi(bundle->getMinSdkVersion()); 4536e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 453728994d8d181c286b39811441ce78399576c2d315Adam Lesinski return 0; 4538e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski} 4539e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4540beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinskibool ResourceTable::shouldGenerateVersionedResource( 4541beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski const sp<ResourceTable::ConfigList>& configList, 4542beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski const ConfigDescription& sourceConfig, 4543beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski const int sdkVersionToGenerate) { 4544f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski assert(sdkVersionToGenerate > sourceConfig.sdkVersion); 4545526d73be4a3a2714fa6112769e16fb6cd0194451Adam Lesinski assert(configList != NULL); 4546f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& entries 4547f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski = configList->getEntries(); 4548f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski ssize_t idx = entries.indexOfKey(sourceConfig); 4549f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski 4550f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski // The source config came from this list, so it should be here. 4551f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski assert(idx >= 0); 4552f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski 4553beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // The next configuration either only varies in sdkVersion, or it is completely different 4554beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // and therefore incompatible. If it is incompatible, we must generate the versioned resource. 4555f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski 4556beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // NOTE: The ordering of configurations takes sdkVersion as higher precedence than other 4557beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // qualifiers, so we need to iterate through the entire list to be sure there 4558beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // are no higher sdk level versions of this resource. 4559f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski ConfigDescription tempConfig(sourceConfig); 4560beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski for (size_t i = static_cast<size_t>(idx) + 1; i < entries.size(); i++) { 4561beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski const ConfigDescription& nextConfig = entries.keyAt(i); 4562beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski tempConfig.sdkVersion = nextConfig.sdkVersion; 4563beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski if (tempConfig == nextConfig) { 4564beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // The two configs are the same, check the sdk version. 4565beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski return sdkVersionToGenerate < nextConfig.sdkVersion; 4566beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski } 4567f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski } 4568beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski 4569beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski // No match was found, so we should generate the versioned resource. 4570beb9e33bfb79847c25aac98e39f3ea620a953ef7Adam Lesinski return true; 4571f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski} 4572f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski 457382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski/** 457482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Modifies the entries in the resource table to account for compatibility 457582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * issues with older versions of Android. 457682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 457782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * This primarily handles the issue of private/public attribute clashes 457882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * in framework resources. 457982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 458082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * AAPT has traditionally assigned resource IDs to public attributes, 458182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * and then followed those public definitions with private attributes. 458282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 458382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC --- 458482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color 458582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background 458682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 458782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE --- 458882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/secret 458982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/shhh 459082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 459182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Each release, when attributes are added, they take the place of the private 459282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attributes and the private attributes are shifted down again. 459382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 459482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PUBLIC --- 459582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010234 | attr/color 459682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010235 | attr/background 459782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010236 | attr/shinyNewAttr 459882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010237 | attr/highlyValuedFeature 459982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 460082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * --- PRIVATE --- 460182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010238 | attr/secret 460282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * | 0x01010239 | attr/shhh 460382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 460482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * Platform code may look for private attributes set in a theme. If an app 460582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * compiled against a newer version of the platform uses a new public 460682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute that happens to have the same ID as the private attribute 460782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * the older platform is expecting, then the behavior is undefined. 460882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * 460982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * We get around this by detecting any newly defined attributes (in L), 461082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * copy the resource into a -v21 qualified resource, and delete the 461182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute from the original resource. This ensures that older platforms 461282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * don't see the new attribute, but when running on L+ platforms, the 461382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski * attribute will be respected. 461482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski */ 461582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle) { 461628994d8d181c286b39811441ce78399576c2d315Adam Lesinski const int minSdk = getMinSdkVersion(bundle); 461728994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (minSdk >= SDK_LOLLIPOP_MR1) { 461828994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Lollipop MR1 and up handles public attributes differently, no 461928994d8d181c286b39811441ce78399576c2d315Adam Lesinski // need to do any compat modifications. 4620e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NO_ERROR; 462182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 462282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 462382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const String16 attr16("attr"); 462482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 462582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t packageCount = mOrderedPackages.size(); 462682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t pi = 0; pi < packageCount; pi++) { 462782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski sp<Package> p = mOrderedPackages.itemAt(pi); 462882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (p == NULL || p->getTypes().size() == 0) { 462982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski // Empty, skip! 463082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 463182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 463282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 463382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t typeCount = p->getOrderedTypes().size(); 463482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t ti = 0; ti < typeCount; ti++) { 463582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski sp<Type> t = p->getOrderedTypes().itemAt(ti); 463682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (t == NULL) { 463782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 463882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 463982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 464082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t configCount = t->getOrderedConfigs().size(); 464182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t ci = 0; ci < configCount; ci++) { 464282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci); 464382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (c == NULL) { 464482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 464582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 464682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 464782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski Vector<key_value_pair_t<ConfigDescription, sp<Entry> > > entriesToAdd; 464882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const DefaultKeyedVector<ConfigDescription, sp<Entry> >& entries = 464982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski c->getEntries(); 465082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t entryCount = entries.size(); 465182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t ei = 0; ei < entryCount; ei++) { 46529b8528fee4eed35b8e887ded0851d08eb2b10db6Chih-Hung Hsieh const sp<Entry>& e = entries.valueAt(ei); 465382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (e == NULL || e->getType() != Entry::TYPE_BAG) { 465482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 465582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 465682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 465782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const ConfigDescription& config = entries.keyAt(ei); 465828994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (config.sdkVersion >= SDK_LOLLIPOP_MR1) { 465982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 466082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 466182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 466228994d8d181c286b39811441ce78399576c2d315Adam Lesinski KeyedVector<int, Vector<String16> > attributesToRemove; 466382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const KeyedVector<String16, Item>& bag = e->getBag(); 466482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t bagCount = bag.size(); 466582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t bi = 0; bi < bagCount; bi++) { 466682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const uint32_t attrId = getResId(bag.keyAt(bi), &attr16); 466728994d8d181c286b39811441ce78399576c2d315Adam Lesinski const int sdkLevel = getPublicAttributeSdkLevel(attrId); 466828994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) { 466928994d8d181c286b39811441ce78399576c2d315Adam Lesinski AaptUtil::appendValue(attributesToRemove, sdkLevel, bag.keyAt(bi)); 467082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 467182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 467282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 467382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski if (attributesToRemove.isEmpty()) { 467482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski continue; 467582a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 467682a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 467728994d8d181c286b39811441ce78399576c2d315Adam Lesinski const size_t sdkCount = attributesToRemove.size(); 467828994d8d181c286b39811441ce78399576c2d315Adam Lesinski for (size_t i = 0; i < sdkCount; i++) { 467928994d8d181c286b39811441ce78399576c2d315Adam Lesinski const int sdkLevel = attributesToRemove.keyAt(i); 468028994d8d181c286b39811441ce78399576c2d315Adam Lesinski 4681f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski if (!shouldGenerateVersionedResource(c, config, sdkLevel)) { 4682f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski // There is a style that will override this generated one. 4683f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski continue; 4684f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski } 4685f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski 468628994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Duplicate the entry under the same configuration 468728994d8d181c286b39811441ce78399576c2d315Adam Lesinski // but with sdkVersion == sdkLevel. 468828994d8d181c286b39811441ce78399576c2d315Adam Lesinski ConfigDescription newConfig(config); 468928994d8d181c286b39811441ce78399576c2d315Adam Lesinski newConfig.sdkVersion = sdkLevel; 469028994d8d181c286b39811441ce78399576c2d315Adam Lesinski 469128994d8d181c286b39811441ce78399576c2d315Adam Lesinski sp<Entry> newEntry = new Entry(*e); 469228994d8d181c286b39811441ce78399576c2d315Adam Lesinski 469328994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Remove all items that have a higher SDK level than 469428994d8d181c286b39811441ce78399576c2d315Adam Lesinski // the one we are synthesizing. 469528994d8d181c286b39811441ce78399576c2d315Adam Lesinski for (size_t j = 0; j < sdkCount; j++) { 469628994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (j == i) { 469728994d8d181c286b39811441ce78399576c2d315Adam Lesinski continue; 469828994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 469928994d8d181c286b39811441ce78399576c2d315Adam Lesinski 470028994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (attributesToRemove.keyAt(j) > sdkLevel) { 470128994d8d181c286b39811441ce78399576c2d315Adam Lesinski const size_t attrCount = attributesToRemove[j].size(); 470228994d8d181c286b39811441ce78399576c2d315Adam Lesinski for (size_t k = 0; k < attrCount; k++) { 470328994d8d181c286b39811441ce78399576c2d315Adam Lesinski newEntry->removeFromBag(attributesToRemove[j][k]); 470428994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 470528994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 470628994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 470728994d8d181c286b39811441ce78399576c2d315Adam Lesinski 470828994d8d181c286b39811441ce78399576c2d315Adam Lesinski entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >( 470928994d8d181c286b39811441ce78399576c2d315Adam Lesinski newConfig, newEntry)); 471028994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 471182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 471282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski // Remove the attribute from the original. 471382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t i = 0; i < attributesToRemove.size(); i++) { 471428994d8d181c286b39811441ce78399576c2d315Adam Lesinski for (size_t j = 0; j < attributesToRemove[i].size(); j++) { 471528994d8d181c286b39811441ce78399576c2d315Adam Lesinski e->removeFromBag(attributesToRemove[i][j]); 471628994d8d181c286b39811441ce78399576c2d315Adam Lesinski } 471782a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 471882a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 471982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 472082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski const size_t entriesToAddCount = entriesToAdd.size(); 472182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski for (size_t i = 0; i < entriesToAddCount; i++) { 4722f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski assert(entries.indexOfKey(entriesToAdd[i].key) < 0); 472382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 4724f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski if (bundle->getVerbose()) { 4725f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski entriesToAdd[i].value->getPos() 4726f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.", 472728994d8d181c286b39811441ce78399576c2d315Adam Lesinski entriesToAdd[i].key.sdkVersion, 4728f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski String8(p->getName()).string(), 4729f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski String8(t->getName()).string(), 4730f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski String8(entriesToAdd[i].value->getName()).string(), 4731f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski entriesToAdd[i].key.toString().string()); 4732f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski } 473382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski 4734978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski sp<Entry> newEntry = t->getEntry(c->getName(), 4735978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski entriesToAdd[i].value->getPos(), 4736978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski &entriesToAdd[i].key); 4737978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski 4738978ab9d92934b79409638cf220de3002fea8d505Adam Lesinski *newEntry = *entriesToAdd[i].value; 473982a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 474082a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 474182a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 474282a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski } 474382a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski return NO_ERROR; 474482a2dd8efe48d3a4e04655f01329da857ace4b7dAdam Lesinski} 4745e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 47464d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakiconst String16 kTransitionElements[] = { 47474d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("fade"), 47484d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("changeBounds"), 47494d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("slide"), 47504d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("explode"), 47514d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("changeImageTransform"), 47524d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("changeTransform"), 47534d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("changeClipBounds"), 47544d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("autoTransition"), 47554d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("recolor"), 47564d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("changeScroll"), 47574d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("transitionSet"), 47584d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("transition"), 47594d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki String16("transitionManager"), 47604d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki}; 47614d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki 47624d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const String16& name) { 47634d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki for (int i = 0, size = sizeof(kTransitionElements) / sizeof(kTransitionElements[0]); 47644d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki i < size; ++i) { 47654d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (name == kTransitionElements[i]) { 47664d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki return true; 47674d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 47684d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 47694d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki return false; 47704d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki} 47714d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki 4772cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinskibool ResourceTable::versionForCompat(const Bundle* bundle, const String16& resourceName, 4773cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski const sp<AaptFile>& target, const sp<XMLNode>& root) { 4774cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski XMLNode* node = root.get(); 4775cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski while (node->getType() != XMLNode::TYPE_ELEMENT) { 4776cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // We're assuming the root element is what we're looking for, which can only be under a 4777cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // bunch of namespace declarations. 4778cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (node->getChildren().size() != 1) { 4779cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Not sure what to do, bail. 4780cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return false; 4781cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4782cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski node = node->getChildren().itemAt(0).get(); 4783cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4784cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4785cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (node->getElementNamespace().size() != 0) { 4786cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Not something we care about. 4787cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return false; 4788cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4789cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4790cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski int versionedSdk = 0; 4791cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (node->getElementName() == String16("adaptive-icon")) { 4792cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski versionedSdk = SDK_O; 4793cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4794cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4795cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski const int minSdkVersion = getMinSdkVersion(bundle); 4796cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski const ConfigDescription config(target->getGroupEntry().toParams()); 4797cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (versionedSdk <= minSdkVersion || versionedSdk <= config.sdkVersion) { 4798cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return false; 4799cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4800cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4801cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()), 4802cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String16(target->getResourceType()), resourceName); 4803cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski if (!shouldGenerateVersionedResource(cl, config, versionedSdk)) { 4804cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return false; 4805cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski } 4806cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4807cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Remove the original entry. 4808cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski cl->removeEntry(config); 4809cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4810cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // We need to wholesale version this file. 4811cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski ConfigDescription newConfig(config); 4812cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski newConfig.sdkVersion = versionedSdk; 4813cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), 4814cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski AaptGroupEntry(newConfig), target->getResourceType()); 4815cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String8 resPath = String8::format("res/%s/%s.xml", 4816cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski newFile->getGroupEntry().toDirName(target->getResourceType()).string(), 4817cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String8(resourceName).string()); 4818cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski resPath.convertToResPath(); 4819cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4820cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Add a resource table entry. 4821cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski addEntry(SourcePos(), 4822cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String16(mAssets->getPackage()), 4823cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String16(target->getResourceType()), 4824cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski resourceName, 4825cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski String16(resPath), 4826cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski NULL, 4827cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski &newConfig); 4828cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4829cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Schedule this to be compiled. 4830cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski CompileResourceWorkItem item; 4831cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski item.resourceName = resourceName; 4832cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski item.resPath = resPath; 4833cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski item.file = newFile; 4834cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski item.xmlRoot = root->clone(); 483554b58ba5cc2c341b39355e265f760fe0654f77a7Adam Lesinski item.needsCompiling = true; 4836cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski mWorkQueue.push(item); 4837cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4838cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski // Now mark the old entry as deleted. 4839cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski return true; 4840cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski} 4841cf1f1d9128853f0fa0cef657e2bbb7bf6904c732Adam Lesinski 4842e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinskistatus_t ResourceTable::modifyForCompat(const Bundle* bundle, 4843e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const String16& resourceName, 4844e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<AaptFile>& target, 4845e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const sp<XMLNode>& root) { 48466e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski const String16 vector16("vector"); 48476e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski const String16 animatedVector16("animated-vector"); 4848010df88f90a40f8c521ccde8d6a541e70a044fb7ztenghui const String16 pathInterpolator16("pathInterpolator"); 4849205548561c67a3c05163d17057a1fc76a338ec15ztenghui const String16 objectAnimator16("objectAnimator"); 4850ab2a38c03d54fad1ed0873ac091959ee38823cd6ztenghui const String16 gradient16("gradient"); 4851e78a8169665c19b5539508f113093b6c2a4b80deNick Butcher const String16 animatedSelector16("animated-selector"); 48526e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski 485328994d8d181c286b39811441ce78399576c2d315Adam Lesinski const int minSdk = getMinSdkVersion(bundle); 485428994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (minSdk >= SDK_LOLLIPOP_MR1) { 485528994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Lollipop MR1 and up handles public attributes differently, no 485628994d8d181c286b39811441ce78399576c2d315Adam Lesinski // need to do any compat modifications. 4857e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NO_ERROR; 4858e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4859e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 486028994d8d181c286b39811441ce78399576c2d315Adam Lesinski const ConfigDescription config(target->getGroupEntry().toParams()); 486128994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (target->getResourceType() == "" || config.sdkVersion >= SDK_LOLLIPOP_MR1) { 48626e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski // Skip resources that have no type (AndroidManifest.xml) or are already version qualified 48636e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski // with v21 or higher. 4864e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NO_ERROR; 4865e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4866e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4867ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski sp<XMLNode> newRoot = NULL; 4868f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski int sdkVersionToGenerate = SDK_LOLLIPOP_MR1; 4869e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4870e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski Vector<sp<XMLNode> > nodesToVisit; 4871e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski nodesToVisit.push(root); 4872e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski while (!nodesToVisit.isEmpty()) { 4873e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski sp<XMLNode> node = nodesToVisit.top(); 4874e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski nodesToVisit.pop(); 4875e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 48766e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski if (bundle->getNoVersionVectors() && (node->getElementName() == vector16 || 4877010df88f90a40f8c521ccde8d6a541e70a044fb7ztenghui node->getElementName() == animatedVector16 || 4878205548561c67a3c05163d17057a1fc76a338ec15ztenghui node->getElementName() == objectAnimator16 || 4879ab2a38c03d54fad1ed0873ac091959ee38823cd6ztenghui node->getElementName() == pathInterpolator16 || 4880e78a8169665c19b5539508f113093b6c2a4b80deNick Butcher node->getElementName() == gradient16 || 4881e78a8169665c19b5539508f113093b6c2a4b80deNick Butcher node->getElementName() == animatedSelector16)) { 48826e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski // We were told not to version vector tags, so skip the children here. 48836e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski continue; 48846e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski } 48856e46056abc1c2803ed7f195bab169bbb1cacec6bAdam Lesinski 48864d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki if (bundle->getNoVersionTransitions() && (IsTransitionElement(node->getElementName()))) { 48874d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki // We were told not to version transition tags, so skip the children here. 48884d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki continue; 48894d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki } 48904d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki 4891e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes(); 4892ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski for (size_t i = 0; i < attrs.size(); i++) { 4893e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const XMLNode::attribute_entry& attr = attrs[i]; 489428994d8d181c286b39811441ce78399576c2d315Adam Lesinski const int sdkLevel = getPublicAttributeSdkLevel(attr.nameResId); 489528994d8d181c286b39811441ce78399576c2d315Adam Lesinski if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) { 4896ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski if (newRoot == NULL) { 4897ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski newRoot = root->clone(); 4898ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski } 4899ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski 490028994d8d181c286b39811441ce78399576c2d315Adam Lesinski // Find the smallest sdk version that we need to synthesize for 490128994d8d181c286b39811441ce78399576c2d315Adam Lesinski // and do that one. Subsequent versions will be processed on 490228994d8d181c286b39811441ce78399576c2d315Adam Lesinski // the next pass. 4903f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski sdkVersionToGenerate = std::min(sdkLevel, sdkVersionToGenerate); 490428994d8d181c286b39811441ce78399576c2d315Adam Lesinski 4905ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski if (bundle->getVerbose()) { 4906ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski SourcePos(node->getFilename(), node->getStartLineNumber()).printf( 4907ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski "removing attribute %s%s%s from <%s>", 4908ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski String8(attr.ns).string(), 4909ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski (attr.ns.size() == 0 ? "" : ":"), 4910ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski String8(attr.name).string(), 4911ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski String8(node->getElementName()).string()); 4912ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski } 4913ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski node->removeAttribute(i); 4914ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski i--; 4915e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4916e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4917e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4918e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski // Schedule a visit to the children. 4919e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const Vector<sp<XMLNode> >& children = node->getChildren(); 4920e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski const size_t childCount = children.size(); 4921e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski for (size_t i = 0; i < childCount; i++) { 4922e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski nodesToVisit.push(children[i]); 4923e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4924e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4925e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4926ea4e5ecc27793b5c1dd2eda291f752b3f900ee6cAdam Lesinski if (newRoot == NULL) { 4927e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NO_ERROR; 4928e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4929e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4930e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski // Look to see if we already have an overriding v21 configuration. 4931e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()), 4932e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski String16(target->getResourceType()), resourceName); 4933f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski if (shouldGenerateVersionedResource(cl, config, sdkVersionToGenerate)) { 4934e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski // We don't have an overriding entry for v21, so we must duplicate this one. 4935f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski ConfigDescription newConfig(config); 4936f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski newConfig.sdkVersion = sdkVersionToGenerate; 4937e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), 4938e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski AaptGroupEntry(newConfig), target->getResourceType()); 493907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8 resPath = String8::format("res/%s/%s.xml", 4940e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski newFile->getGroupEntry().toDirName(target->getResourceType()).string(), 494107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8(resourceName).string()); 4942e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski resPath.convertToResPath(); 4943e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4944e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski // Add a resource table entry. 4945f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski if (bundle->getVerbose()) { 4946f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski SourcePos(target->getSourceFile(), -1).printf( 4947f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.", 494828994d8d181c286b39811441ce78399576c2d315Adam Lesinski newConfig.sdkVersion, 4949f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski mAssets->getPackage().string(), 4950f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski newFile->getResourceType().string(), 4951f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski String8(resourceName).string(), 4952f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski newConfig.toString().string()); 4953f15de2e2151ae48338afd27f3ebd33fce5009103Adam Lesinski } 4954e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4955e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski addEntry(SourcePos(), 4956e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski String16(mAssets->getPackage()), 4957e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski String16(target->getResourceType()), 4958e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski resourceName, 4959e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski String16(resPath), 4960e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski NULL, 4961e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski &newConfig); 4962e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski 4963e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski // Schedule this to be compiled. 4964e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski CompileResourceWorkItem item; 4965e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski item.resourceName = resourceName; 4966e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski item.resPath = resPath; 4967e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski item.file = newFile; 496807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski item.xmlRoot = newRoot; 496907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski item.needsCompiling = false; // This step occurs after we parse/assign, so we don't need 497007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // to do it again. 4971e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski mWorkQueue.push(item); 4972e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski } 4973e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski return NO_ERROR; 4974e572c011feabf6319ba836cf5bc4c3baa0ba6a85Adam Lesinski} 4975de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski 4976f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinskivoid ResourceTable::getDensityVaryingResources( 4977f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) { 4978de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const ConfigDescription nullConfig; 4979de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski 4980de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const size_t packageCount = mOrderedPackages.size(); 4981de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski for (size_t p = 0; p < packageCount; p++) { 4982de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const Vector<sp<Type> >& types = mOrderedPackages[p]->getOrderedTypes(); 4983de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const size_t typeCount = types.size(); 4984de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski for (size_t t = 0; t < typeCount; t++) { 4985081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski const sp<Type>& type = types[t]; 4986081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski if (type == NULL) { 4987081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski continue; 4988081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski } 4989081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski 4990081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski const Vector<sp<ConfigList> >& configs = type->getOrderedConfigs(); 4991de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const size_t configCount = configs.size(); 4992de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski for (size_t c = 0; c < configCount; c++) { 4993081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski const sp<ConfigList>& configList = configs[c]; 4994081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski if (configList == NULL) { 4995081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski continue; 4996081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski } 4997081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski 4998f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries 4999081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski = configList->getEntries(); 5000de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const size_t configEntryCount = configEntries.size(); 5001de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski for (size_t ce = 0; ce < configEntryCount; ce++) { 5002081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski const sp<Entry>& entry = configEntries.valueAt(ce); 5003081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski if (entry == NULL) { 5004081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski continue; 5005081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski } 5006081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski 5007de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski const ConfigDescription& config = configEntries.keyAt(ce); 5008de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski if (AaptConfig::isDensityOnly(config)) { 5009de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski // This configuration only varies with regards to density. 5010f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski const Symbol symbol( 5011f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski mOrderedPackages[p]->getName(), 5012081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski type->getName(), 5013081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski configList->getName(), 5014f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski getResId(mOrderedPackages[p], types[t], 5015081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski configList->getEntryIndex())); 5016081d1b4cf602fdd7302b597e6bf902cb415bc3a8Adam Lesinski 5017de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski 5018f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski AaptUtil::appendValue(resources, symbol, 5019f45d2fad2ecd3cb3c4aeee3014763e01b59eab09Adam Lesinski SymbolDefinition(symbol, config, entry->getPos())); 5020de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski } 5021de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski } 5022de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski } 5023de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski } 5024de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski } 5025de7de47fef1dcaa26d553665d89e4d3792325c3fAdam Lesinski} 502607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 502707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinskistatic String16 buildNamespace(const String16& package) { 502807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return String16("http://schemas.android.com/apk/res/") + package; 502907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski} 503007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 503107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinskistatic sp<XMLNode> findOnlyChildElement(const sp<XMLNode>& parent) { 503207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const Vector<sp<XMLNode> >& children = parent->getChildren(); 503307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski sp<XMLNode> onlyChild; 503407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski for (size_t i = 0; i < children.size(); i++) { 503507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (children[i]->getType() != XMLNode::TYPE_CDATA) { 503607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (onlyChild != NULL) { 503707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return NULL; 503807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 503907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski onlyChild = children[i]; 504007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 504107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 504207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return onlyChild; 504307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski} 504407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 504507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski/** 504607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * Detects use of the `bundle' format and extracts nested resources into their own top level 504707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * resources. The bundle format looks like this: 504807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * 504907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <!-- res/drawable/bundle.xml --> 505007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <animated-vector xmlns:aapt="http://schemas.android.com/aapt"> 505107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <aapt:attr name="android:drawable"> 505207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <vector android:width="60dp" 505307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:height="60dp"> 505407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <path android:name="v" 505507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:fillColor="#000000" 505607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:pathData="M300,70 l 0,-70 70,..." /> 505707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * </vector> 505807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * </aapt:attr> 505907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * </animated-vector> 506007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * 506107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * When AAPT sees the <aapt:attr> tag, it will extract its single element and its children 506207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * into a new high-level resource, assigning it a name and ID. Then value of the `name` 506307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * attribute must be a resource attribute. That resource attribute is inserted into the parent 506407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * with the reference to the extracted resource as the value. 506507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * 506607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <!-- res/drawable/bundle.xml --> 506707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <animated-vector android:drawable="@drawable/bundle_1.xml"> 506807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * </animated-vector> 506907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * 507007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <!-- res/drawable/bundle_1.xml --> 507107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <vector android:width="60dp" 507207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:height="60dp"> 507307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * <path android:name="v" 507407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:fillColor="#000000" 507507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * android:pathData="M300,70 l 0,-70 70,..." /> 507607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski * </vector> 507707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski */ 507807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinskistatus_t ResourceTable::processBundleFormat(const Bundle* bundle, 507907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16& resourceName, 508007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<AaptFile>& target, 508107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<XMLNode>& root) { 508207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski Vector<sp<XMLNode> > namespaces; 508307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (root->getType() == XMLNode::TYPE_NAMESPACE) { 508407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski namespaces.push(root); 508507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 508607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return processBundleFormatImpl(bundle, resourceName, target, root, &namespaces); 508707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski} 508807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 508907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinskistatus_t ResourceTable::processBundleFormatImpl(const Bundle* bundle, 509007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16& resourceName, 509107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<AaptFile>& target, 509207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<XMLNode>& parent, 509307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski Vector<sp<XMLNode> >* namespaces) { 509407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16 kAaptNamespaceUri16("http://schemas.android.com/aapt"); 509507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16 kName16("name"); 509607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16 kAttr16("attr"); 509707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const String16 kAssetPackage16(mAssets->getPackage()); 509807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 509907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski Vector<sp<XMLNode> >& children = parent->getChildren(); 510007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski for (size_t i = 0; i < children.size(); i++) { 510107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<XMLNode>& child = children[i]; 510207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 510307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (child->getType() == XMLNode::TYPE_CDATA) { 510407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski continue; 510507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } else if (child->getType() == XMLNode::TYPE_NAMESPACE) { 510607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski namespaces->push(child); 510707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 510807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 510907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (child->getElementNamespace() != kAaptNamespaceUri16 || 511007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski child->getElementName() != kAttr16) { 511107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski status_t result = processBundleFormatImpl(bundle, resourceName, target, child, 511207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski namespaces); 511307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (result != NO_ERROR) { 511407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return result; 511507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 511607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 511707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (child->getType() == XMLNode::TYPE_NAMESPACE) { 511807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski namespaces->pop(); 511907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 512007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski continue; 512107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 512207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 512307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // This is the <aapt:attr> tag. Look for the 'name' attribute. 512407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski SourcePos source(child->getFilename(), child->getStartLineNumber()); 512507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 512607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski sp<XMLNode> nestedRoot = findOnlyChildElement(child); 512707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (nestedRoot == NULL) { 512807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source.error("<%s:%s> must have exactly one child element", 512907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8(child->getElementNamespace()).string(), 513007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8(child->getElementName()).string()); 513107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 513207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 513307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 513407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Find the special attribute 'parent-attr'. This attribute's value contains 513507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // the resource attribute for which this element should be assigned in the parent. 513607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const XMLNode::attribute_entry* attr = child->getAttribute(String16(), kName16); 513707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (attr == NULL) { 513807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source.error("inline resource definition must specify an attribute via 'name'"); 513907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 514007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 514107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 514207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Parse the attribute name. 514307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const char* errorMsg = NULL; 514407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String16 attrPackage, attrType, attrName; 514507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski bool result = ResTable::expandResourceRef(attr->string.string(), 514607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski attr->string.size(), 514707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski &attrPackage, &attrType, &attrName, 514807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski &kAttr16, &kAssetPackage16, 514907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski &errorMsg, NULL); 515007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (!result) { 515107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source.error("invalid attribute name for 'name': %s", errorMsg); 515207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 515307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 515407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 515507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (attrType != kAttr16) { 515607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // The value of the 'name' attribute must be an attribute reference. 515707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source.error("value of 'name' must be an attribute reference."); 515807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 515907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 516007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 516107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Generate a name for this nested resource and try to add it to the table. 516207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // We do this in a loop because the name may be taken, in which case we will 516307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // increment a suffix until we succeed. 516407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8 nestedResourceName; 516507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8 nestedResourcePath; 516607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski int suffix = 1; 516707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski while (true) { 516807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // This child element will be extracted into its own resource file. 516907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Generate a name and path for it from its parent. 517007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedResourceName = String8::format("%s_%d", 517107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8(resourceName).string(), suffix++); 517207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedResourcePath = String8::format("res/%s/%s.xml", 517307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski target->getGroupEntry().toDirName(target->getResourceType()) 517407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski .string(), 517507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedResourceName.string()); 517607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 517707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Lookup or create the entry for this name. 517807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski sp<Entry> entry = getEntry(kAssetPackage16, 517907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String16(target->getResourceType()), 518007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String16(nestedResourceName), 518107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source, 518207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski false, 518307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski &target->getGroupEntry().toParams(), 518407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski true); 518507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (entry == NULL) { 518607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 518707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 518807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 518907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (entry->getType() == Entry::TYPE_UNKNOWN) { 519007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // The value for this resource has never been set, 519107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // meaning we're good! 519207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski entry->setItem(source, String16(nestedResourcePath)); 519307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski break; 519407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 519507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 519607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // We failed (name already exists), so try with a different name 519707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // (increment the suffix). 519807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 519907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 520007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (bundle->getVerbose()) { 520107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski source.printf("generating nested resource %s:%s/%s", 520207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski mAssets->getPackage().string(), target->getResourceType().string(), 520307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedResourceName.string()); 520407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 520507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 520607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Build the attribute reference and assign it to the parent. 520707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String16 nestedResourceRef = String16(String8::format("@%s:%s/%s", 520807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski mAssets->getPackage().string(), target->getResourceType().string(), 520907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedResourceName.string())); 521007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 521107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String16 attrNs = buildNamespace(attrPackage); 521207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski if (parent->getAttribute(attrNs, attrName) != NULL) { 521307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski SourcePos(parent->getFilename(), parent->getStartLineNumber()) 521407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski .error("parent of nested resource already defines attribute '%s:%s'", 521507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski String8(attrPackage).string(), String8(attrName).string()); 521607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return UNKNOWN_ERROR; 521707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 521807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 521907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Add the reference to the inline resource. 522007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski parent->addAttribute(attrNs, attrName, nestedResourceRef); 522107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 522207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Remove the <aapt:attr> child element from here. 522307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski children.removeAt(i); 522407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski i--; 522507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 522607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Append all namespace declarations that we've seen on this branch in the XML tree 522707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // to this resource. 522807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // We do this because the order of namespace declarations and prefix usage is determined 522907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // by the developer and we do not want to override any decisions. Be conservative. 523007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski for (size_t nsIndex = namespaces->size(); nsIndex > 0; nsIndex--) { 523107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski const sp<XMLNode>& ns = namespaces->itemAt(nsIndex - 1); 523207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski sp<XMLNode> newNs = XMLNode::newNamespace(ns->getFilename(), ns->getNamespacePrefix(), 523307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski ns->getNamespaceUri()); 523407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski newNs->addChild(nestedRoot); 523507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski nestedRoot = newNs; 523607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 523707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski 523807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski // Schedule compilation of the nested resource. 523907dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski CompileResourceWorkItem workItem; 524007dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski workItem.resPath = nestedResourcePath; 524107dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski workItem.resourceName = String16(nestedResourceName); 524207dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski workItem.xmlRoot = nestedRoot; 524307dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski workItem.file = new AaptFile(target->getSourceFile(), target->getGroupEntry(), 524407dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski target->getResourceType()); 524507dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski mWorkQueue.push(workItem); 524607dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski } 524707dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski return NO_ERROR; 524807dfd2d8642f8a3630ca6429f740865a0c0bfdf7Adam Lesinski} 5249