X-Git-Url: https://git.saurik.com/android/aapt.git/blobdiff_plain/d0c4b8109ffb0ad08dcbf29203c71af10715fd87..b5a0aec21ed839862f44bbd6e0c24c0e3a3433a4:/Resource.cpp?ds=inline diff --git a/Resource.cpp b/Resource.cpp index fd6ddb5..41ee88b 100644 --- a/Resource.cpp +++ b/Resource.cpp @@ -45,13 +45,6 @@ static String8 parseResourceName(const String8& leaf) } } -class ResourceTypeSet : public RefBase, - public KeyedVector > -{ -public: - ResourceTypeSet(); -}; - ResourceTypeSet::ResourceTypeSet() :RefBase(), KeyedVector >() @@ -181,7 +174,7 @@ static sp getResourceFile(const sp& assets, bool makeIfNec static status_t parsePackage(const sp& assets, const sp& grp) { if (grp->getFiles().size() != 1) { - fprintf(stderr, "WARNING: Multiple AndroidManifest.xml files found, using %s\n", + fprintf(stderr, "warning: Multiple AndroidManifest.xml files found, using %s\n", grp->getFiles().valueAt(0)->getPrintableSource().string()); } @@ -426,18 +419,133 @@ static void checkForIds(const String8& path, ResXMLParser& parser) if (code == ResXMLTree::START_TAG) { ssize_t index = parser.indexOfAttribute(NULL, "id"); if (index >= 0) { - fprintf(stderr, "%s:%d: WARNING: found plain 'id' attribute; did you mean the new 'android:id' name?\n", + fprintf(stderr, "%s:%d: warning: found plain 'id' attribute; did you mean the new 'android:id' name?\n", path.string(), parser.getLineNumber()); } } } } +static bool applyFileOverlay(const sp& assets, + const sp& baseSet, + const char *resType) +{ + // Replace any base level files in this category with any found from the overlay + // Also add any found only in the overlay. + sp overlay = assets->getOverlay(); + String8 resTypeString(resType); + + // work through the linked list of overlays + while (overlay.get()) { + KeyedVector >* overlayRes = overlay->getResources(); + + // get the overlay resources of the requested type + ssize_t index = overlayRes->indexOfKey(resTypeString); + if (index >= 0) { + sp overlaySet = overlayRes->valueAt(index); + + // for each of the resources, check for a match in the previously built + // non-overlay "baseset". + size_t overlayCount = overlaySet->size(); + for (size_t overlayIndex=0; overlayIndexindexOfKey(overlaySet->keyAt(overlayIndex)); + if (baseIndex < UNKNOWN_ERROR) { + // look for same flavor. For a given file (strings.xml, for example) + // there may be a locale specific or other flavors - we want to match + // the same flavor. + sp overlayGroup = overlaySet->valueAt(overlayIndex); + sp baseGroup = baseSet->valueAt(baseIndex); + + DefaultKeyedVector > baseFiles = + baseGroup->getFiles(); + DefaultKeyedVector > overlayFiles = + overlayGroup->getFiles(); + size_t overlayGroupSize = overlayFiles.size(); + for (size_t overlayGroupIndex = 0; + overlayGroupIndexremoveFile(baseFileIndex); + } else { + // didn't find a match fall through and add it.. + } + baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex)); + } + } else { + // this group doesn't exist (a file that's only in the overlay) + fprintf(stderr, "aapt: error: " + "*** Resource file '%s' exists only in an overlay\n", + overlaySet->keyAt(overlayIndex).string()); + return false; + } + } + // this overlay didn't have resources for this type + } + // try next overlay + overlay = overlay->getOverlay(); + } + return true; +} + +void addTagAttribute(const sp& node, const char* ns8, + const char* attr8, const char* value) +{ + if (value == NULL) { + return; + } + + const String16 ns(ns8); + const String16 attr(attr8); + + if (node->getAttribute(ns, attr) != NULL) { + fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s)\n", + String8(attr).string(), String8(ns).string()); + return; + } + + node->addAttribute(ns, attr, String16(value)); +} + +status_t massageManifest(Bundle* bundle, sp root) +{ + root = root->searchElement(String16(), String16("manifest")); + if (root == NULL) { + fprintf(stderr, "No tag.\n"); + return UNKNOWN_ERROR; + } + + addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode", + bundle->getVersionCode()); + addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName", + bundle->getVersionName()); + + if (bundle->getMinSdkVersion() != NULL + || bundle->getTargetSdkVersion() != NULL + || bundle->getMaxSdkVersion() != NULL) { + sp vers = root->getChildElement(String16(), String16("uses-sdk")); + if (vers == NULL) { + vers = XMLNode::newElement(root->getFilename(), String16(), String16("uses-sdk")); + root->insertChildAt(vers, 0); + } + + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion", + bundle->getMinSdkVersion()); + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion", + bundle->getTargetSdkVersion()); + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion", + bundle->getMaxSdkVersion()); + } + + return NO_ERROR; +} + #define ASSIGN_IT(n) \ do { \ - ssize_t index = resources.indexOfKey(String8(#n)); \ + ssize_t index = resources->indexOfKey(String8(#n)); \ if (index >= 0) { \ - n ## s = resources.valueAt(index); \ + n ## s = resources->valueAt(index); \ } \ } while (0) @@ -468,18 +576,16 @@ status_t buildResources(Bundle* bundle, const sp& assets) NOISY(printf("Found %d included resource packages\n", (int)table.size())); - sp res = assets->getDirs().valueFor(String8("res")); - // -------------------------------------------------------------- // First, gather all resource information. // -------------------------------------------------------------- // resType -> leafName -> group - KeyedVector > resources; - collect_files(assets, &resources); + KeyedVector > *resources = + new KeyedVector >; + collect_files(assets, resources); sp drawables; - sp valuess; sp layouts; sp anims; sp xmls; @@ -492,10 +598,30 @@ status_t buildResources(Bundle* bundle, const sp& assets) ASSIGN_IT(anim); ASSIGN_IT(xml); ASSIGN_IT(raw); - ASSIGN_IT(values); ASSIGN_IT(color); ASSIGN_IT(menu); + assets->setResources(resources); + // now go through any resource overlays and collect their files + sp current = assets->getOverlay(); + while(current.get()) { + KeyedVector > *resources = + new KeyedVector >; + current->setResources(resources); + collect_files(current, resources); + current = current->getOverlay(); + } + // apply the overlay files to the base set + if (!applyFileOverlay(assets, drawables, "drawable") || + !applyFileOverlay(assets, layouts, "layout") || + !applyFileOverlay(assets, anims, "anim") || + !applyFileOverlay(assets, xmls, "xml") || + !applyFileOverlay(assets, raws, "raw") || + !applyFileOverlay(assets, colors, "color") || + !applyFileOverlay(assets, menus, "menu")) { + return UNKNOWN_ERROR; + } + bool hasErrors = false; if (drawables != NULL) { @@ -538,17 +664,26 @@ status_t buildResources(Bundle* bundle, const sp& assets) } } - if (valuess != NULL) { - ResourceDirIterator it(valuess, String8("values")); - ssize_t res; - while ((res=it.next()) == NO_ERROR) { - sp file = it.getFile(); - - res = compileResourceFile(bundle, assets, file, it.getParams(), &table); - if (res != NO_ERROR) { - hasErrors = true; + // compile resources + current = assets; + while(current.get()) { + KeyedVector > *resources = + current->getResources(); + + ssize_t index = resources->indexOfKey(String8("values")); + if (index >= 0) { + ResourceDirIterator it(resources->valueAt(index), String8("values")); + ssize_t res; + while ((res=it.next()) == NO_ERROR) { + sp file = it.getFile(); + res = compileResourceFile(bundle, assets, file, it.getParams(), + (current!=assets), &table); + if (res != NO_ERROR) { + hasErrors = true; + } } } + current = current->getOverlay(); } if (colors != NULL) { @@ -926,7 +1061,15 @@ status_t buildResources(Bundle* bundle, const sp& assets) // Generate final compiled manifest file. manifestFile->clearData(); - err = compileXmlFile(assets, manifestFile, &table); + sp manifestTree = XMLNode::parse(manifestFile); + if (manifestTree == NULL) { + return UNKNOWN_ERROR; + } + err = massageManifest(bundle, manifestTree); + if (err < NO_ERROR) { + return err; + } + err = compileXmlFile(assets, manifestTree, manifestFile, &table); if (err < NO_ERROR) { return err; } @@ -968,6 +1111,7 @@ status_t buildResources(Bundle* bundle, const sp& assets) printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile()); } table.writePublicDefinitions(String16(assets->getPackage()), fp); + fclose(fp); } NOISY( @@ -985,7 +1129,6 @@ status_t buildResources(Bundle* bundle, const sp& assets) return err; } } - return err; }