}
}
-class ResourceTypeSet : public RefBase,
- public KeyedVector<String8,sp<AaptGroup> >
-{
-public:
- ResourceTypeSet();
-};
-
ResourceTypeSet::ResourceTypeSet()
:RefBase(),
KeyedVector<String8,sp<AaptGroup> >()
static status_t parsePackage(const sp<AaptAssets>& assets, const sp<AaptGroup>& 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());
}
ResourceDirIterator it(set, String8("drawable"));
Vector<sp<AaptFile> > newNameFiles;
Vector<String8> newNamePaths;
+ bool hasErrors = false;
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
res = preProcessImage(bundle, assets, it.getFile(), NULL);
- if (res != NO_ERROR) {
- return res;
+ if (res < NO_ERROR) {
+ hasErrors = true;
}
}
- return NO_ERROR;
+ return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
}
status_t postProcessImages(const sp<AaptAssets>& assets,
const sp<ResourceTypeSet>& set)
{
ResourceDirIterator it(set, String8("drawable"));
+ bool hasErrors = false;
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
res = postProcessImage(assets, table, it.getFile());
- if (res != NO_ERROR) {
- return res;
+ if (res < NO_ERROR) {
+ hasErrors = true;
}
}
- return res < NO_ERROR ? res : (status_t)NO_ERROR;
+ return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
}
static void collect_files(const sp<AaptDir>& dir,
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<AaptAssets>& assets,
+ const sp<ResourceTypeSet>& 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<AaptAssets> overlay = assets->getOverlay();
+ String8 resTypeString(resType);
+
+ // work through the linked list of overlays
+ while (overlay.get()) {
+ KeyedVector<String8, sp<ResourceTypeSet> >* overlayRes = overlay->getResources();
+
+ // get the overlay resources of the requested type
+ ssize_t index = overlayRes->indexOfKey(resTypeString);
+ if (index >= 0) {
+ sp<ResourceTypeSet> 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; overlayIndex<overlayCount; overlayIndex++) {
+ size_t baseIndex = baseSet->indexOfKey(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<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
+ sp<AaptGroup> baseGroup = baseSet->valueAt(baseIndex);
+
+ DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
+ baseGroup->getFiles();
+ DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
+ overlayGroup->getFiles();
+ size_t overlayGroupSize = overlayFiles.size();
+ for (size_t overlayGroupIndex = 0;
+ overlayGroupIndex<overlayGroupSize;
+ overlayGroupIndex++) {
+ size_t baseFileIndex =
+ baseFiles.indexOfKey(overlayFiles.keyAt(overlayGroupIndex));
+ if(baseFileIndex < UNKNOWN_ERROR) {
+ baseGroup->removeFile(baseFileIndex);
+ } else {
+ // didn't find a match fall through and add it..
+ }
+ baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex));
+ assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
+ }
+ } else {
+ // this group doesn't exist (a file that's only in the overlay)
+ baseSet->add(overlaySet->keyAt(overlayIndex),
+ overlaySet->valueAt(overlayIndex));
+ // make sure all flavors are defined in the resources.
+ sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
+ DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
+ overlayGroup->getFiles();
+ size_t overlayGroupSize = overlayFiles.size();
+ for (size_t overlayGroupIndex = 0;
+ overlayGroupIndex<overlayGroupSize;
+ overlayGroupIndex++) {
+ assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
+ }
+ }
+ }
+ // this overlay didn't have resources for this type
+ }
+ // try next overlay
+ overlay = overlay->getOverlay();
+ }
+ return true;
+}
+
+void addTagAttribute(const sp<XMLNode>& 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<XMLNode> root)
+{
+ root = root->searchElement(String16(), String16("manifest"));
+ if (root == NULL) {
+ fprintf(stderr, "No <manifest> 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<XMLNode> 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)
NOISY(printf("Found %d included resource packages\n", (int)table.size()));
- sp<AaptDir> res = assets->getDirs().valueFor(String8("res"));
-
// --------------------------------------------------------------
// First, gather all resource information.
// --------------------------------------------------------------
// resType -> leafName -> group
- KeyedVector<String8, sp<ResourceTypeSet> > resources;
- collect_files(assets, &resources);
+ KeyedVector<String8, sp<ResourceTypeSet> > *resources =
+ new KeyedVector<String8, sp<ResourceTypeSet> >;
+ collect_files(assets, resources);
sp<ResourceTypeSet> drawables;
- sp<ResourceTypeSet> valuess;
sp<ResourceTypeSet> layouts;
sp<ResourceTypeSet> anims;
sp<ResourceTypeSet> xmls;
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<AaptAssets> current = assets->getOverlay();
+ while(current.get()) {
+ KeyedVector<String8, sp<ResourceTypeSet> > *resources =
+ new KeyedVector<String8, sp<ResourceTypeSet> >;
+ 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) {
}
}
- if (valuess != NULL) {
- ResourceDirIterator it(valuess, String8("values"));
- ssize_t res;
- while ((res=it.next()) == NO_ERROR) {
- sp<AaptFile> 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<String8, sp<ResourceTypeSet> > *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<AaptFile> 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) {
// Generate final compiled manifest file.
manifestFile->clearData();
- err = compileXmlFile(assets, manifestFile, &table);
+ sp<XMLNode> 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;
}
printf(" Writing public definitions to %s.\n", bundle->getPublicOutputFile());
}
table.writePublicDefinitions(String16(assets->getPackage()), fp);
+ fclose(fp);
}
NOISY(
return err;
}
}
-
return err;
}
NA = idents.size();
+ bool deprecated = false;
+
String16 comment = symbols->getComment(realClassName);
fprintf(fp, "%s/** ", indentStr);
if (comment.size() > 0) {
- fprintf(fp, "%s\n", String8(comment).string());
+ String8 cmt(comment);
+ fprintf(fp, "%s\n", cmt.string());
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
+ }
} else {
fprintf(fp, "Attributes that can be used with a %s.\n", nclassName.string());
}
}
fprintf(fp, "%s */\n", getIndentSpace(indent));
+ if (deprecated) {
+ fprintf(fp, "%s@Deprecated\n", indentStr);
+ }
+
fprintf(fp,
"%spublic static final int[] %s = {\n"
"%s",
//printf("%s:%s/%s: 0x%08x\n", String8(package16).string(),
// String8(attr16).string(), String8(name16).string(), typeSpecFlags);
const bool pub = (typeSpecFlags&ResTable_typeSpec::SPEC_PUBLIC) != 0;
-
+
+ bool deprecated = false;
+
fprintf(fp, "%s/**\n", indentStr);
if (comment.size() > 0) {
+ String8 cmt(comment);
fprintf(fp, "%s <p>\n%s @attr description\n", indentStr, indentStr);
- fprintf(fp, "%s %s\n", indentStr, String8(comment).string());
+ fprintf(fp, "%s %s\n", indentStr, cmt.string());
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
+ }
} else {
fprintf(fp,
"%s <p>This symbol is the offset where the {@link %s.R.attr#%s}\n"
indentStr, nclassName.string());
}
if (typeComment.size() > 0) {
- fprintf(fp, "\n\n%s %s\n", indentStr, String8(typeComment).string());
+ String8 cmt(typeComment);
+ fprintf(fp, "\n\n%s %s\n", indentStr, cmt.string());
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
+ }
}
if (comment.size() > 0) {
if (pub) {
fprintf(fp, "%s @attr name %s:%s\n", indentStr,
"android", String8(name).string());
fprintf(fp, "%s*/\n", indentStr);
+ if (deprecated) {
+ fprintf(fp, "%s@Deprecated\n", indentStr);
+ }
fprintf(fp,
"%spublic static final int %s_%s = %d;\n",
indentStr, nclassName.string(),
}
String16 comment(sym.comment);
bool haveComment = false;
+ bool deprecated = false;
if (comment.size() > 0) {
haveComment = true;
+ String8 cmt(comment);
fprintf(fp,
"%s/** %s\n",
- getIndentSpace(indent), String8(comment).string());
+ getIndentSpace(indent), cmt.string());
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
+ }
} else if (sym.isPublic && !includePrivate) {
sym.sourcePos.warning("No comment for public symbol %s:%s/%s",
assets->getPackage().string(), className.string(),
}
String16 typeComment(sym.typeComment);
if (typeComment.size() > 0) {
+ String8 cmt(typeComment);
if (!haveComment) {
haveComment = true;
fprintf(fp,
- "%s/** %s\n",
- getIndentSpace(indent), String8(typeComment).string());
+ "%s/** %s\n", getIndentSpace(indent), cmt.string());
} else {
fprintf(fp,
- "%s %s\n",
- getIndentSpace(indent), String8(typeComment).string());
+ "%s %s\n", getIndentSpace(indent), cmt.string());
+ }
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
}
}
if (haveComment) {
fprintf(fp,"%s */\n", getIndentSpace(indent));
}
+ if (deprecated) {
+ fprintf(fp, "%s@Deprecated\n", getIndentSpace(indent));
+ }
fprintf(fp, "%spublic static final int %s=0x%08x;\n",
getIndentSpace(indent),
String8(name).string(), (int)sym.int32Val);
return UNKNOWN_ERROR;
}
String16 comment(sym.comment);
+ bool deprecated = false;
if (comment.size() > 0) {
+ String8 cmt(comment);
fprintf(fp,
"%s/** %s\n"
"%s */\n",
- getIndentSpace(indent), String8(comment).string(),
+ getIndentSpace(indent), cmt.string(),
getIndentSpace(indent));
+ if (strstr(cmt.string(), "@deprecated") != NULL) {
+ deprecated = true;
+ }
} else if (sym.isPublic && !includePrivate) {
sym.sourcePos.warning("No comment for public symbol %s:%s/%s",
assets->getPackage().string(), className.string(),
String8(sym.name).string());
}
+ if (deprecated) {
+ fprintf(fp, "%s@Deprecated\n", getIndentSpace(indent));
+ }
fprintf(fp, "%spublic static final String %s=\"%s\";\n",
getIndentSpace(indent),
String8(name).string(), sym.stringVal.string());