X-Git-Url: https://git.saurik.com/android/aapt.git/blobdiff_plain/3c80e5c0dc993f14ed11bca00e023ce8c073a7f4..054e9517d9586fb31af8d3bb8dcffc0b76e06ac4:/ResourceTable.cpp
diff --git a/ResourceTable.cpp b/ResourceTable.cpp
index 3641458..0b531c2 100644
--- a/ResourceTable.cpp
+++ b/ResourceTable.cpp
@@ -23,12 +23,26 @@ status_t compileXmlFile(const sp& assets,
if (root == NULL) {
return UNKNOWN_ERROR;
}
+
+ return compileXmlFile(assets, root, target, table, options);
+}
+
+status_t compileXmlFile(const sp& assets,
+ const sp& root,
+ const sp& target,
+ ResourceTable* table,
+ int options)
+{
if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
root->removeWhitespace(true, NULL);
} else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
root->removeWhitespace(false, NULL);
}
+ if ((options&XML_COMPILE_UTF8) != 0) {
+ root->setUTF8(true);
+ }
+
bool hasErrors = false;
if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) {
@@ -115,7 +129,7 @@ static const flag_entry gFormatFlags[] = {
"a floating point value, such as \"1.2
\"."},
{ dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION,
"a dimension value, which is a floating point number appended with a unit such as \"14.5sp
\".\n"
- "Available units are: px (pixels), db (density-independent pixels), sp (scaled pixels based on preferred font size),\n"
+ "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n"
"in (inches), mm (millimeters)." },
{ fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION,
"a fractional value, which is a floating point number appended with either % or %p, such as \"14.5%
\".\n"
@@ -368,7 +382,7 @@ static status_t compileAttribute(const sp& in,
}
attr.createIfNeeded(outTable);
if (!attr.hasErrors) {
- char buf[10];
+ char buf[11];
sprintf(buf, "%d", l10n_required);
err = outTable->addBag(attr.sourcePos, myPackage, attr16, attr.ident,
String16(""), String16("^l10n"), String16(buf), NULL, NULL);
@@ -470,22 +484,22 @@ static status_t compileAttribute(const sp& in,
enumOrFlagsComment.append((attr.type&ResTable_map::TYPE_ENUM)
? String16(" be one of the following constant values.")
: String16(" be one or more (separated by '|') of the following constant values."));
- enumOrFlagsComment.append(String16("
\n\n"
+ enumOrFlagsComment.append(String16("\n\n"
"\n"
"\n"
"\n"
- "Constant | Value | Description |
"));
+ "Constant | Value | Description |
"));
}
- enumOrFlagsComment.append(String16("\n"));
+ enumOrFlagsComment.append(String16("\n"));
enumOrFlagsComment.append(itemIdent);
- enumOrFlagsComment.append(String16(" | "));
+ enumOrFlagsComment.append(String16(" | "));
enumOrFlagsComment.append(value);
- enumOrFlagsComment.append(String16(" | "));
+ enumOrFlagsComment.append(String16(" | "));
if (block.getComment(&len)) {
enumOrFlagsComment.append(String16(block.getComment(&len)));
}
- enumOrFlagsComment.append(String16(" | "));
+ enumOrFlagsComment.append(String16(" |
"));
err = outTable->addBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
myPackage,
@@ -546,6 +560,7 @@ status_t parseAndAddBag(Bundle* bundle,
const String16& itemIdent,
int32_t curFormat,
bool pseudolocalize,
+ const bool overwrite,
ResourceTable* outTable)
{
status_t err;
@@ -572,7 +587,7 @@ status_t parseAndAddBag(Bundle* bundle,
err = outTable->addBag(SourcePos(in->getPrintableSource(), block->getLineNumber()),
myPackage, curType, ident, parentIdent, itemIdent, str,
- &spans, &config, false, false, curFormat);
+ &spans, &config, overwrite, false, curFormat);
return err;
}
@@ -588,6 +603,7 @@ status_t parseAndAddEntry(Bundle* bundle,
bool curIsStyled,
int32_t curFormat,
bool pseudolocalize,
+ const bool overwrite,
ResourceTable* outTable)
{
status_t err;
@@ -610,7 +626,7 @@ status_t parseAndAddEntry(Bundle* bundle,
err = outTable->addEntry(SourcePos(in->getPrintableSource(), block->getLineNumber()),
myPackage, curType, ident, str, &spans, &config,
- false, curFormat);
+ false, curFormat, overwrite);
return err;
}
@@ -619,6 +635,7 @@ status_t compileResourceFile(Bundle* bundle,
const sp& assets,
const sp& in,
const ResTable_config& defParams,
+ const bool overwrite,
ResourceTable* outTable)
{
ResXMLTree block;
@@ -641,13 +658,16 @@ status_t compileResourceFile(Bundle* bundle,
const String16 bool16("bool");
const String16 integer16("integer");
const String16 dimen16("dimen");
+ const String16 fraction16("fraction");
const String16 style16("style");
const String16 plurals16("plurals");
const String16 array16("array");
const String16 string_array16("string-array");
const String16 integer_array16("integer-array");
const String16 public16("public");
+ const String16 public_padding16("public-padding");
const String16 private_symbols16("private-symbols");
+ const String16 add_resource16("add-resource");
const String16 skip16("skip");
const String16 eat_comment16("eat-comment");
@@ -681,7 +701,7 @@ status_t compileResourceFile(Bundle* bundle,
bool hasErrors = false;
- uint32_t nextPublicId = 0;
+ DefaultKeyedVector nextPublicId(0);
ResXMLTree::event_code_t code;
do {
@@ -714,6 +734,7 @@ status_t compileResourceFile(Bundle* bundle,
String16 curType;
int32_t curFormat = ResTable_map::TYPE_ANY;
bool curIsBag = false;
+ bool curIsBagReplaceOnOverwrite = false;
bool curIsStyled = false;
bool curIsPseudolocalizable = false;
bool localHasErrors = false;
@@ -770,15 +791,15 @@ status_t compileResourceFile(Bundle* bundle,
hasErrors = localHasErrors = true;
} else {
ident = identValue.data;
- nextPublicId = ident+1;
+ nextPublicId.replaceValueFor(type, ident+1);
}
- } else if (nextPublicId == 0) {
+ } else if (nextPublicId.indexOfKey(type) < 0) {
srcPos.error("No 'id' attribute supplied ,"
" and no previous id defined in this file.\n");
hasErrors = localHasErrors = true;
} else if (!localHasErrors) {
- ident = nextPublicId;
- nextPublicId++;
+ ident = nextPublicId.valueFor(type);
+ nextPublicId.replaceValueFor(type, ident+1);
}
if (!localHasErrors) {
@@ -812,6 +833,116 @@ status_t compileResourceFile(Bundle* bundle,
}
continue;
+ } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
+ SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+
+ String16 type;
+ ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
+ if (typeIdx < 0) {
+ srcPos.error("A 'type' attribute is required for \n");
+ hasErrors = localHasErrors = true;
+ }
+ type = String16(block.getAttributeStringValue(typeIdx, &len));
+
+ String16 name;
+ ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+ if (nameIdx < 0) {
+ srcPos.error("A 'name' attribute is required for \n");
+ hasErrors = localHasErrors = true;
+ }
+ name = String16(block.getAttributeStringValue(nameIdx, &len));
+
+ uint32_t start = 0;
+ ssize_t startIdx = block.indexOfAttribute(NULL, "start");
+ if (startIdx >= 0) {
+ const char16_t* startStr = block.getAttributeStringValue(startIdx, &len);
+ Res_value startValue;
+ if (!ResTable::stringToInt(startStr, len, &startValue)) {
+ srcPos.error("Given 'start' attribute is not an integer: %s\n",
+ String8(block.getAttributeStringValue(startIdx, &len)).string());
+ hasErrors = localHasErrors = true;
+ } else {
+ start = startValue.data;
+ }
+ } else if (nextPublicId.indexOfKey(type) < 0) {
+ srcPos.error("No 'start' attribute supplied ,"
+ " and no previous id defined in this file.\n");
+ hasErrors = localHasErrors = true;
+ } else if (!localHasErrors) {
+ start = nextPublicId.valueFor(type);
+ }
+
+ uint32_t end = 0;
+ ssize_t endIdx = block.indexOfAttribute(NULL, "end");
+ if (endIdx >= 0) {
+ const char16_t* endStr = block.getAttributeStringValue(endIdx, &len);
+ Res_value endValue;
+ if (!ResTable::stringToInt(endStr, len, &endValue)) {
+ srcPos.error("Given 'end' attribute is not an integer: %s\n",
+ String8(block.getAttributeStringValue(endIdx, &len)).string());
+ hasErrors = localHasErrors = true;
+ } else {
+ end = endValue.data;
+ }
+ } else {
+ srcPos.error("No 'end' attribute supplied \n");
+ hasErrors = localHasErrors = true;
+ }
+
+ if (end >= start) {
+ nextPublicId.replaceValueFor(type, end+1);
+ } else {
+ srcPos.error("Padding start '%ul' is after end '%ul'\n",
+ start, end);
+ hasErrors = localHasErrors = true;
+ }
+
+ String16 comment(
+ block.getComment(&len) ? block.getComment(&len) : nulStr);
+ for (uint32_t curIdent=start; curIdent<=end; curIdent++) {
+ if (localHasErrors) {
+ break;
+ }
+ String16 curName(name);
+ char buf[64];
+ sprintf(buf, "%d", (int)(end-curIdent+1));
+ curName.append(String16(buf));
+
+ err = outTable->addEntry(srcPos, myPackage, type, curName,
+ String16("padding"), NULL, &curParams, false,
+ ResTable_map::TYPE_STRING, overwrite);
+ if (err < NO_ERROR) {
+ hasErrors = localHasErrors = true;
+ break;
+ }
+ err = outTable->addPublic(srcPos, myPackage, type,
+ curName, curIdent);
+ if (err < NO_ERROR) {
+ hasErrors = localHasErrors = true;
+ break;
+ }
+ sp symbols = assets->getSymbolsFor(String8("R"));
+ if (symbols != NULL) {
+ symbols = symbols->addNestedSymbol(String8(type), srcPos);
+ }
+ if (symbols != NULL) {
+ symbols->makeSymbolPublic(String8(curName), srcPos);
+ symbols->appendComment(String8(curName), comment, srcPos);
+ } else {
+ srcPos.error("Unable to create symbols!\n");
+ hasErrors = localHasErrors = true;
+ }
+ }
+
+ while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code == ResXMLTree::END_TAG) {
+ if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) {
+ break;
+ }
+ }
+ }
+ continue;
+
} else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
String16 pkg;
ssize_t pkgIdx = block.indexOfAttribute(NULL, "package");
@@ -834,6 +965,36 @@ status_t compileResourceFile(Bundle* bundle,
}
continue;
+ } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
+ SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+
+ String16 typeName;
+ ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
+ if (typeIdx < 0) {
+ srcPos.error("A 'type' attribute is required for \n");
+ hasErrors = localHasErrors = true;
+ }
+ typeName = String16(block.getAttributeStringValue(typeIdx, &len));
+
+ String16 name;
+ ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+ if (nameIdx < 0) {
+ srcPos.error("A 'name' attribute is required for \n");
+ hasErrors = localHasErrors = true;
+ }
+ name = String16(block.getAttributeStringValue(nameIdx, &len));
+
+ outTable->canAddEntry(srcPos, myPackage, typeName, name);
+
+ while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code == ResXMLTree::END_TAG) {
+ if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
+ break;
+ }
+ }
+ }
+ continue;
+
} else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
@@ -979,7 +1140,7 @@ status_t compileResourceFile(Bundle* bundle,
if (locale.size() > 0) {
fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists"
" in locale '%s'\n", String8(name).string(),
- bundle->getResourceSourceDir(),
+ bundle->getResourceSourceDirs()[0],
locale.string());
// hasErrors = localHasErrors = true;
} else {
@@ -1019,6 +1180,10 @@ status_t compileResourceFile(Bundle* bundle,
curTag = &dimen16;
curType = dimen16;
curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_DIMENSION;
+ } else if (strcmp16(block.getElementName(&len), fraction16.string()) == 0) {
+ curTag = &fraction16;
+ curType = fraction16;
+ curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_FRACTION;
} else if (strcmp16(block.getElementName(&len), bag16.string()) == 0) {
curTag = &bag16;
curIsBag = true;
@@ -1042,6 +1207,7 @@ status_t compileResourceFile(Bundle* bundle,
curTag = &array16;
curType = array16;
curIsBag = true;
+ curIsBagReplaceOnOverwrite = true;
ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
if (formatIdx >= 0) {
String16 formatStr = String16(block.getAttributeStringValue(
@@ -1060,12 +1226,14 @@ status_t compileResourceFile(Bundle* bundle,
curType = array16;
curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
curIsBag = true;
+ curIsBagReplaceOnOverwrite = true;
curIsPseudolocalizable = true;
} else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
curTag = &integer_array16;
curType = array16;
curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER;
curIsBag = true;
+ curIsBagReplaceOnOverwrite = true;
} else {
SourcePos(in->getPrintableSource(), block.getLineNumber()).error(
"Found tag %s where item is expected\n",
@@ -1100,8 +1268,10 @@ status_t compileResourceFile(Bundle* bundle,
}
if (!localHasErrors) {
- err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()),
- myPackage, curType, ident, parentIdent, &curParams);
+ err = outTable->startBag(SourcePos(in->getPrintableSource(),
+ block.getLineNumber()), myPackage, curType, ident,
+ parentIdent, &curParams,
+ overwrite, curIsBagReplaceOnOverwrite);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -1172,7 +1342,8 @@ status_t compileResourceFile(Bundle* bundle,
block.getPosition(&parserPosition);
err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
- ident, parentIdent, itemIdent, curFormat, false, outTable);
+ ident, parentIdent, itemIdent, curFormat,
+ false, overwrite, outTable);
if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
&& bundle->getPseudolocalize()) {
@@ -1181,7 +1352,7 @@ status_t compileResourceFile(Bundle* bundle,
block.setPosition(parserPosition);
err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
curType, ident, parentIdent, itemIdent, curFormat, true,
- outTable);
+ overwrite, outTable);
#endif
}
}
@@ -1204,7 +1375,7 @@ status_t compileResourceFile(Bundle* bundle,
block.getPosition(&parserPosition);
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
- *curTag, curIsStyled, curFormat, false, outTable);
+ *curTag, curIsStyled, curFormat, false, overwrite, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1215,7 +1386,7 @@ status_t compileResourceFile(Bundle* bundle,
// pseudolocalize here
block.setPosition(parserPosition);
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
- ident, *curTag, curIsStyled, curFormat, true, outTable);
+ ident, *curTag, curIsStyled, curFormat, true, overwrite, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -1297,7 +1468,7 @@ status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp* style,
const ResTable_config* params,
const bool doSetIndex,
- const int32_t format)
+ const int32_t format,
+ const bool overwrite)
{
// Check for adding entries in other packages... for now we do
// nothing. We need to do the right thing here to support skinning.
@@ -1379,12 +1551,13 @@ status_t ResourceTable::addEntry(const SourcePos& sourcePos,
String8(value).string());
}
#endif
-
- sp e = getEntry(package, type, name, sourcePos, params, doSetIndex);
+
+ sp e = getEntry(package, type, name, sourcePos, overwrite,
+ params, doSetIndex);
if (e == NULL) {
return UNKNOWN_ERROR;
}
- status_t err = e->setItem(sourcePos, value, style, format);
+ status_t err = e->setItem(sourcePos, value, style, format, overwrite);
if (err == NO_ERROR) {
mNumLocal++;
}
@@ -1397,8 +1570,11 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos,
const String16& name,
const String16& bagParent,
const ResTable_config* params,
+ bool overlay,
bool replace, bool isId)
{
+ status_t result = NO_ERROR;
+
// Check for adding entries in other packages... for now we do
// nothing. We need to do the right thing here to support skinning.
uint32_t rid = mAssets->getIncludedResources()
@@ -1415,8 +1591,24 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos,
sourcePos.file.striing(), sourcePos.line, String8(type).string());
}
#endif
-
- sp e = getEntry(package, type, name, sourcePos, params);
+ if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
+ bool canAdd = false;
+ sp p = mPackages.valueFor(package);
+ if (p != NULL) {
+ sp t = p->getTypes().valueFor(type);
+ if (t != NULL) {
+ if (t->getCanAddEntries().indexOf(name) >= 0) {
+ canAdd = true;
+ }
+ }
+ }
+ if (!canAdd) {
+ sourcePos.error("Resource does not already exist in overlay at '%s'; use to add.\n",
+ String8(name).string());
+ return UNKNOWN_ERROR;
+ }
+ }
+ sp e = getEntry(package, type, name, sourcePos, overlay, params);
if (e == NULL) {
return UNKNOWN_ERROR;
}
@@ -1432,8 +1624,15 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos,
}
e->setParent(bagParent);
}
-
- return e->makeItABag(sourcePos);
+
+ if ((result = e->makeItABag(sourcePos)) != NO_ERROR) {
+ return result;
+ }
+
+ if (overlay && replace) {
+ return e->emptyBag(sourcePos);
+ }
+ return result;
}
status_t ResourceTable::addBag(const SourcePos& sourcePos,
@@ -1463,8 +1662,7 @@ status_t ResourceTable::addBag(const SourcePos& sourcePos,
sourcePos.file.striing(), sourcePos.line, String8(type).string());
}
#endif
-
- sp e = getEntry(package, type, name, sourcePos, params);
+ sp e = getEntry(package, type, name, sourcePos, replace, params);
if (e == NULL) {
return UNKNOWN_ERROR;
}
@@ -1573,6 +1771,15 @@ bool ResourceTable::appendTypeComment(const String16& package,
return false;
}
+void ResourceTable::canAddEntry(const SourcePos& pos,
+ const String16& package, const String16& type, const String16& name)
+{
+ sp t = getType(package, type, pos);
+ if (t != NULL) {
+ t->canAddEntry(name);
+ }
+}
+
size_t ResourceTable::size() const {
return mPackages.size();
}
@@ -2125,7 +2332,7 @@ ResourceTable::validateLocalizations(void)
// Look for strings with no default localization
if (configSet.count(defaultLocale) == 0) {
fprintf(stdout, "aapt: warning: string '%s' has no default translation in %s; found:",
- String8(nameIter->first).string(), mBundle->getResourceSourceDir());
+ String8(nameIter->first).string(), mBundle->getResourceSourceDirs()[0]);
for (set::iterator locales = configSet.begin();
locales != configSet.end();
locales++) {
@@ -2160,15 +2367,13 @@ ResourceTable::validateLocalizations(void)
// consider that string to have fulfilled the localization requirement.
String8 region(config.string(), 2);
if (configSet.find(region) == configSet.end()) {
- // TODO: force an error if there is no default to fall back to
if (configSet.count(defaultLocale) == 0) {
fprintf(stdout, "aapt: warning: "
"*** string '%s' has no default or required localization "
"for '%s' in %s\n",
String8(nameIter->first).string(),
config.string(),
- mBundle->getResourceSourceDir());
- //err = UNKNOWN_ERROR;
+ mBundle->getResourceSourceDirs()[0]);
}
}
}
@@ -2267,6 +2472,12 @@ ResourceFilter::match(const ResTable_config& config)
if (!match(AXIS_ORIENTATION, config.orientation)) {
return false;
}
+ if (!match(AXIS_UIMODETYPE, (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE))) {
+ return false;
+ }
+ if (!match(AXIS_UIMODENIGHT, (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT))) {
+ return false;
+ }
if (!match(AXIS_DENSITY, config.density)) {
return false;
}
@@ -2304,7 +2515,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp& dest)
// Iterate through all data, collecting all values (strings,
// references, etc).
- StringPool valueStrings;
+ StringPool valueStrings = StringPool(false, bundle->getUTF8());
for (pi=0; pi p = mOrderedPackages.itemAt(pi);
if (p->getTypes().size() == 0) {
@@ -2312,8 +2523,8 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp& dest)
continue;
}
- StringPool typeStrings;
- StringPool keyStrings;
+ StringPool typeStrings = StringPool(false, bundle->getUTF8());
+ StringPool keyStrings = StringPool(false, bundle->getUTF8());
const size_t N = p->getOrderedTypes().size();
for (size_t ti=0; ti& dest)
ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
- "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+ "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
ti+1,
config.mcc, config.mnc,
config.language[0] ? config.language[0] : '-',
@@ -2477,6 +2688,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp& dest)
config.country[0] ? config.country[0] : '-',
config.country[1] ? config.country[1] : '-',
config.orientation,
+ config.uiMode,
config.touchscreen,
config.density,
config.keyboard,
@@ -2506,7 +2718,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp& dest)
tHeader->entriesStart = htodl(typeSize);
tHeader->config = config;
NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
- "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+ "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
ti+1,
tHeader->config.mcc, tHeader->config.mnc,
tHeader->config.language[0] ? tHeader->config.language[0] : '-',
@@ -2514,6 +2726,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp& dest)
tHeader->config.country[0] ? tHeader->config.country[0] : '-',
tHeader->config.country[1] ? tHeader->config.country[1] : '-',
tHeader->config.orientation,
+ tHeader->config.uiMode,
tHeader->config.touchscreen,
tHeader->config.density,
tHeader->config.keyboard,
@@ -2728,7 +2941,8 @@ status_t ResourceTable::Entry::makeItABag(const SourcePos& sourcePos)
status_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
const String16& value,
const Vector* style,
- int32_t format)
+ int32_t format,
+ const bool overwrite)
{
Item item(sourcePos, false, value, style);
@@ -2740,14 +2954,14 @@ status_t ResourceTable::Entry::setItem(const SourcePos& sourcePos,
item.sourcePos.file.string(), item.sourcePos.line);
return UNKNOWN_ERROR;
}
- if (mType != TYPE_UNKNOWN) {
+ if ( (mType != TYPE_UNKNOWN) && (overwrite == false) ) {
sourcePos.error("Resource entry %s is already defined.\n"
"%s:%d: Originally defined here.\n",
String8(mName).string(),
mItem.sourcePos.file.string(), mItem.sourcePos.line);
return UNKNOWN_ERROR;
}
-
+
mType = TYPE_ITEM;
mItem = item;
mItemFormat = format;
@@ -2788,6 +3002,17 @@ status_t ResourceTable::Entry::addToBag(const SourcePos& sourcePos,
return NO_ERROR;
}
+status_t ResourceTable::Entry::emptyBag(const SourcePos& sourcePos)
+{
+ status_t err = makeItABag(sourcePos);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ mBag.clear();
+ return NO_ERROR;
+}
+
status_t ResourceTable::Entry::generateAttributes(ResourceTable* table,
const String16& package)
{
@@ -3053,14 +3278,27 @@ status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
return NO_ERROR;
}
+void ResourceTable::Type::canAddEntry(const String16& name)
+{
+ mCanAddEntries.add(name);
+}
+
sp ResourceTable::Type::getEntry(const String16& entry,
const SourcePos& sourcePos,
const ResTable_config* config,
- bool doSetIndex)
+ bool doSetIndex,
+ bool overlay,
+ bool autoAddOverlay)
{
int pos = -1;
sp c = mConfigs.valueFor(entry);
if (c == NULL) {
+ if (overlay && !autoAddOverlay && mCanAddEntries.indexOf(entry) < 0) {
+ sourcePos.error("Resource at %s appears in overlay but not"
+ " in the base package; use to add.\n",
+ String8(entry).string());
+ return NULL;
+ }
c = new ConfigList(entry, sourcePos);
mConfigs.add(entry, c);
pos = (int)mOrderedConfigs.size();
@@ -3359,6 +3597,7 @@ sp ResourceTable::getEntry(const String16& package,
const String16& type,
const String16& name,
const SourcePos& sourcePos,
+ bool overlay,
const ResTable_config* config,
bool doSetIndex)
{
@@ -3366,7 +3605,7 @@ sp ResourceTable::getEntry(const String16& package,
if (t == NULL) {
return NULL;
}
- return t->getEntry(name, sourcePos, config, doSetIndex);
+ return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
}
sp ResourceTable::getEntry(uint32_t resID,
@@ -3385,26 +3624,26 @@ sp ResourceTable::getEntry(uint32_t resID,
}
if (p == NULL) {
- fprintf(stderr, "WARNING: Package not found for resource #%08x\n", resID);
+ fprintf(stderr, "warning: Package not found for resource #%08x\n", resID);
return NULL;
}
int tid = Res_GETTYPE(resID);
if (tid < 0 || tid >= (int)p->getOrderedTypes().size()) {
- fprintf(stderr, "WARNING: Type not found for resource #%08x\n", resID);
+ fprintf(stderr, "warning: Type not found for resource #%08x\n", resID);
return NULL;
}
sp t = p->getOrderedTypes()[tid];
int eid = Res_GETENTRY(resID);
if (eid < 0 || eid >= (int)t->getOrderedConfigs().size()) {
- fprintf(stderr, "WARNING: Entry not found for resource #%08x\n", resID);
+ fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
return NULL;
}
sp c = t->getOrderedConfigs()[eid];
if (c == NULL) {
- fprintf(stderr, "WARNING: Entry not found for resource #%08x\n", resID);
+ fprintf(stderr, "warning: Entry not found for resource #%08x\n", resID);
return NULL;
}
@@ -3412,7 +3651,7 @@ sp ResourceTable::getEntry(uint32_t resID,
if (config) cdesc = *config;
sp e = c->getEntries().valueFor(cdesc);
if (c == NULL) {
- fprintf(stderr, "WARNING: Entry configuration not found for resource #%08x\n", resID);
+ fprintf(stderr, "warning: Entry configuration not found for resource #%08x\n", resID);
return NULL;
}
@@ -3430,7 +3669,7 @@ const ResourceTable::Item* ResourceTable::getItem(uint32_t resID, uint32_t attrI
for (size_t i=0; igetBag().valueAt(i);
if (it.bagKeyId == 0) {
- fprintf(stderr, "WARNING: ID not yet assigned to '%s' in bag '%s'\n",
+ fprintf(stderr, "warning: ID not yet assigned to '%s' in bag '%s'\n",
String8(e->getName()).string(),
String8(e->getBag().keyAt(i)).string());
}
@@ -3458,7 +3697,7 @@ bool ResourceTable::getItemValue(
break;
}
}
- fprintf(stderr, "WARNING: Circular reference detected in key '%s' of bag '%s'\n",
+ fprintf(stderr, "warning: Circular reference detected in key '%s' of bag '%s'\n",
String8(e->getName()).string(),
String8(e->getBag().keyAt(i)).string());
return false;
@@ -3479,4 +3718,3 @@ bool ResourceTable::getItemValue(
}
return res;
}
-