diff options
author | Adam Lesinski <adamlesinski@google.com> | 2013-10-04 12:06:38 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2013-10-04 15:14:09 -0700 |
commit | 2b8e82fd51fca815675e7cb32c35da3932f0dc13 (patch) | |
tree | 80ffefd2ff99d2f3d129c7682b014d468a56c7dd /tools/aapt | |
parent | fc141ef20bf871e925fbbbe4bb9af64c67033246 (diff) | |
download | frameworks_base-2b8e82fd51fca815675e7cb32c35da3932f0dc13.zip frameworks_base-2b8e82fd51fca815675e7cb32c35da3932f0dc13.tar.gz frameworks_base-2b8e82fd51fca815675e7cb32c35da3932f0dc13.tar.bz2 |
AAPT emits error for res with no 'default' product
Rather than ignoring resources that do not match the specified
product, we keep track of the ignored ones and make sure that
some variant of the resource that matches the product was processed.
bug:10860838
Change-Id: I804cd04a053269a35b7e1c1cc743b77493337bf9
Diffstat (limited to 'tools/aapt')
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 52ebaf0..f2e5254 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -636,6 +636,30 @@ bool isInProductList(const String16& needle, const String16& haystack) { return false; } +/* + * A simple container that holds a resource type and name. It is ordered first by type then + * by name. + */ +struct type_ident_pair_t { + String16 type; + String16 ident; + + type_ident_pair_t() { }; + type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { } + type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { } + inline bool operator < (const type_ident_pair_t& o) const { + int cmp = compare_type(type, o.type); + if (cmp < 0) { + return true; + } else if (cmp > 0) { + return false; + } else { + return strictly_order_type(ident, o.ident); + } + } +}; + + status_t parseAndAddEntry(Bundle* bundle, const sp<AaptFile>& in, ResXMLTree* block, @@ -650,6 +674,7 @@ status_t parseAndAddEntry(Bundle* bundle, const String16& product, bool pseudolocalize, const bool overwrite, + KeyedVector<type_ident_pair_t, bool>* skippedResourceNames, ResourceTable* outTable) { status_t err; @@ -684,6 +709,13 @@ status_t parseAndAddEntry(Bundle* bundle, if (bundleProduct[0] == '\0') { if (strcmp16(String16("default").string(), product.string()) != 0) { + /* + * This string has a product other than 'default'. Do not add it, + * but record it so that if we do not see the same string with + * product 'default' or no product, then report an error. + */ + skippedResourceNames->replaceValueFor( + type_ident_pair_t(curType, ident), true); return NO_ERROR; } } else { @@ -797,6 +829,11 @@ status_t compileResourceFile(Bundle* bundle, DefaultKeyedVector<String16, uint32_t> nextPublicId(0); + // Stores the resource names that were skipped. Typically this happens when + // AAPT is invoked without a product specified and a resource has no + // 'default' product attribute. + KeyedVector<type_ident_pair_t, bool> skippedResourceNames; + ResXMLTree::event_code_t code; do { code = block.next(); @@ -1544,7 +1581,7 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, *curTag, curIsStyled, curFormat, curIsFormatted, - product, false, overwrite, outTable); + product, false, overwrite, &skippedResourceNames, outTable); if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? hasErrors = localHasErrors = true; @@ -1557,7 +1594,7 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, ident, *curTag, curIsStyled, curFormat, curIsFormatted, product, - true, overwrite, outTable); + true, overwrite, &skippedResourceNames, outTable); if (err != NO_ERROR) { hasErrors = localHasErrors = true; } @@ -1596,6 +1633,30 @@ status_t compileResourceFile(Bundle* bundle, } } + // For every resource defined, there must be exist one variant with a product attribute + // set to 'default' (or no product attribute at all). + // We check to see that for every resource that was ignored because of a mismatched + // product attribute, some product variant of that resource was processed. + for (size_t i = 0; i < skippedResourceNames.size(); i++) { + if (skippedResourceNames[i]) { + const type_ident_pair_t& p = skippedResourceNames.keyAt(i); + if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) { + const char* bundleProduct = + (bundle->getProduct() == NULL) ? "" : bundle->getProduct(); + fprintf(stderr, "In resource file %s: %s\n", + in->getPrintableSource().string(), + curParams.toString().string()); + + fprintf(stderr, "\t%s '%s' does not match product %s.\n" + "\tYou may have forgotten to include a 'default' product variant" + " of the resource.\n", + String8(p.type).string(), String8(p.ident).string(), + bundleProduct[0] == 0 ? "default" : bundleProduct); + return UNKNOWN_ERROR; + } + } + } + return hasErrors ? UNKNOWN_ERROR : NO_ERROR; } @@ -2483,8 +2544,8 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) { String16 comment(c->getComment()); typeSymbols->appendComment(String8(c->getName()), comment, c->getPos()); - //printf("Type symbol %s comment: %s\n", String8(e->getName()).string(), - // String8(comment).string()); + //printf("Type symbol [%08x] %s comment: %s\n", rid, + // String8(c->getName()).string(), String8(comment).string()); comment = c->getTypeComment(); typeSymbols->appendTypeComment(String8(c->getName()), comment); } else { |