String8 leaf(group->getLeaf());
mLeafName = String8(leaf);
mParams = file->getGroupEntry().toParams();
- NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
+ NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d ui=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
group->getPath().string(), mParams.mcc, mParams.mnc,
mParams.language[0] ? mParams.language[0] : '-',
mParams.language[1] ? mParams.language[1] : '-',
mParams.country[0] ? mParams.country[0] : '-',
mParams.country[1] ? mParams.country[1] : '-',
- mParams.orientation,
+ mParams.orientation, mParams.uiMode,
mParams.density, mParams.touchscreen, mParams.keyboard,
mParams.inputFlags, mParams.navigation));
mPath = "res";
&& code != ResXMLTree::BAD_DOCUMENT) {
if (code == ResXMLTree::START_TAG) {
if (strcmp16(block.getElementName(&len), uses_sdk16.string()) == 0) {
- ssize_t minSdkIndex = block.indexOfAttribute("android",
+ ssize_t minSdkIndex = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
"minSdkVersion");
if (minSdkIndex >= 0) {
- String8 minSdkString = String8(
- block.getAttributeStringValue(minSdkIndex, &len));
- bundle->setMinSdkVersion(minSdkString.string());
+ const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
+ const char* minSdk8 = strdup(String8(minSdk16).string());
+ bundle->setMinSdkVersion(minSdk8);
}
}
}
DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
baseGroup->getFiles();
for (size_t i=0; i < baseFiles.size(); i++) {
- printf("baseFile %d has flavor %s\n", i,
+ printf("baseFile %ld has flavor %s\n", i,
baseFiles.keyAt(i).toString().string());
}
for (size_t i=0; i < overlayFiles.size(); i++) {
- printf("overlayFile %d has flavor %s\n", i,
+ printf("overlayFile %ld has flavor %s\n", i,
overlayFiles.keyAt(i).toString().string());
}
}
keyAt(overlayGroupIndex));
if(baseFileIndex < UNKNOWN_ERROR) {
if (bundle->getVerbose()) {
- printf("found a match (%d) for overlay file %s, for flavor %s\n",
+ printf("found a match (%ld) for overlay file %s, for flavor %s\n",
baseFileIndex,
overlayGroup->getLeaf().string(),
overlayFiles.keyAt(overlayGroupIndex).toString().string());
node->addAttribute(ns, attr, String16(value));
}
+static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
+ const String16& attrName) {
+ XMLNode::attribute_entry* attr = node->editAttribute(
+ String16("http://schemas.android.com/apk/res/android"), attrName);
+ if (attr != NULL) {
+ String8 name(attr->string);
+
+ // asdf --> package.asdf
+ // .asdf .a.b --> package.asdf package.a.b
+ // asdf.adsf --> asdf.asdf
+ String8 className;
+ const char* p = name.string();
+ const char* q = strchr(p, '.');
+ if (p == q) {
+ className += package;
+ className += name;
+ } else if (q == NULL) {
+ className += package;
+ className += ".";
+ className += name;
+ } else {
+ className += name;
+ }
+ NOISY(printf("Qualifying class '%s' to '%s'", name.string(), className.string()));
+ attr->string.setTo(String16(className));
+ }
+}
+
status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
{
root = root->searchElement(String16(), String16("manifest"));
addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
bundle->getMaxSdkVersion());
}
+
+ // Deal with manifest package name overrides
+ const char* manifestPackageNameOverride = bundle->getManifestPackageNameOverride();
+ if (manifestPackageNameOverride != NULL) {
+ // Update the actual package name
+ XMLNode::attribute_entry* attr = root->editAttribute(String16(), String16("package"));
+ if (attr == NULL) {
+ fprintf(stderr, "package name is required with --rename-manifest-package.\n");
+ return UNKNOWN_ERROR;
+ }
+ String8 origPackage(attr->string);
+ attr->string.setTo(String16(manifestPackageNameOverride));
+ NOISY(printf("Overriding package '%s' to be '%s'\n", origPackage.string(), manifestPackageNameOverride));
+
+ // Make class names fully qualified
+ sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
+ if (application != NULL) {
+ fullyQualifyClassName(origPackage, application, String16("name"));
+
+ Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(application->getChildren());
+ for (size_t i = 0; i < children.size(); i++) {
+ sp<XMLNode> child = children.editItemAt(i);
+ String8 tag(child->getElementName());
+ if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") {
+ fullyQualifyClassName(origPackage, child, String16("name"));
+ } else if (tag == "activity-alias") {
+ fullyQualifyClassName(origPackage, child, String16("name"));
+ fullyQualifyClassName(origPackage, child, String16("targetActivity"));
+ }
+ }
+ }
+ }
+
+ // Deal with manifest package name overrides
+ const char* instrumentationPackageNameOverride = bundle->getInstrumentationPackageNameOverride();
+ if (instrumentationPackageNameOverride != NULL) {
+ // Fix up instrumentation targets.
+ Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(root->getChildren());
+ for (size_t i = 0; i < children.size(); i++) {
+ sp<XMLNode> child = children.editItemAt(i);
+ String8 tag(child->getElementName());
+ if (tag == "instrumentation") {
+ XMLNode::attribute_entry* attr = child->editAttribute(
+ String16("http://schemas.android.com/apk/res/android"), String16("targetPackage"));
+ if (attr != NULL) {
+ attr->string.setTo(String16(instrumentationPackageNameOverride));
+ }
+ }
+ }
+ }
return NO_ERROR;
}
table.writePublicDefinitions(String16(assets->getPackage()), fp);
fclose(fp);
}
-
+#if 0
NOISY(
ResTable rt;
rt.add(resFile->getData(), resFile->getSize(), NULL);
printf("Generated resources:\n");
rt.print();
)
-
+#endif
// These resources are now considered to be a part of the included
// resources, for others to reference.
err = assets->addIncludedResources(resFile);
depth++;
String8 tag(tree.getElementName(&len));
// printf("Depth %d tag %s\n", depth, tag.string());
+ bool keepTag = false;
if (depth == 1) {
if (tag != "manifest") {
fprintf(stderr, "ERROR: manifest does not start with <manifest> tag\n");
return -1;
}
pkg = getAttribute(tree, NULL, "package", NULL);
- } else if (depth == 2 && tag == "application") {
- inApplication = true;
- }
- if (inApplication) {
- if (tag == "application" || tag == "activity" || tag == "service" || tag == "receiver"
- || tag == "provider") {
- String8 name = getAttribute(tree, "http://schemas.android.com/apk/res/android",
- "name", &error);
- if (error != "") {
- fprintf(stderr, "ERROR: %s\n", error.string());
- return -1;
- }
+ } else if (depth == 2) {
+ if (tag == "application") {
+ inApplication = true;
+ keepTag = true;
+ } else if (tag == "instrumentation") {
+ keepTag = true;
+ }
+ }
+ if (!keepTag && inApplication && depth == 3) {
+ if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") {
+ keepTag = true;
+ }
+ }
+ if (keepTag) {
+ String8 name = getAttribute(tree, "http://schemas.android.com/apk/res/android",
+ "name", &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR: %s\n", error.string());
+ return -1;
+ }
+ if (name.length() > 0) {
// asdf --> package.asdf
// .asdf .a.b --> package.asdf package.a.b
// asdf.adsf --> asdf.asdf
return NO_ERROR;
}
+void
+addProguardKeepRule(ProguardKeepSet* keep, const String8& className,
+ const String8& srcName, int line)
+{
+ String8 rule("-keep class ");
+ rule += className;
+ rule += " { <init>(...); }";
+
+ String8 location("view ");
+ location += srcName;
+ char lineno[20];
+ sprintf(lineno, ":%d", line);
+ location += lineno;
+
+ keep->add(rule, location);
+}
+
status_t
-writeProguardForLayout(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile)
+writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile,
+ const char* startTag, const char* altTag)
{
status_t err;
ResXMLTree tree;
tree.restart();
+ if (startTag != NULL) {
+ bool haveStart = false;
+ while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code != ResXMLTree::START_TAG) {
+ continue;
+ }
+ String8 tag(tree.getElementName(&len));
+ if (tag == startTag) {
+ haveStart = true;
+ }
+ break;
+ }
+ if (!haveStart) {
+ return NO_ERROR;
+ }
+ }
+
while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
if (code != ResXMLTree::START_TAG) {
continue;
// If there is no '.', we'll assume that it's one of the built in names.
if (strchr(tag.string(), '.')) {
- String8 rule("-keep class ");
- rule += tag;
- rule += " { <init>(...); }";
-
- String8 location("view ");
- location += layoutFile->getSourceFile();
- char lineno[20];
- sprintf(lineno, ":%d", tree.getLineNumber());
- location += lineno;
-
- keep->add(rule, location);
+ addProguardKeepRule(keep, tag,
+ layoutFile->getPrintableSource(), tree.getLineNumber());
+ } else if (altTag != NULL && tag == altTag) {
+ ssize_t classIndex = tree.indexOfAttribute(NULL, "class");
+ if (classIndex < 0) {
+ fprintf(stderr, "%s:%d: <view> does not have class attribute.\n",
+ layoutFile->getPrintableSource().string(), tree.getLineNumber());
+ } else {
+ size_t len;
+ addProguardKeepRule(keep,
+ String8(tree.getAttributeStringValue(classIndex, &len)),
+ layoutFile->getPrintableSource(), tree.getLineNumber());
+ }
}
}
writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
{
status_t err;
- sp<AaptDir> layout = assets->resDir(String8("layout"));
-
- if (layout != NULL) {
- const KeyedVector<String8,sp<AaptGroup> > groups = layout->getFiles();
+ const Vector<sp<AaptDir> >& dirs = assets->resDirs();
+ const size_t K = dirs.size();
+ for (size_t k=0; k<K; k++) {
+ const sp<AaptDir>& d = dirs.itemAt(k);
+ const String8& dirName = d->getLeaf();
+ const char* startTag = NULL;
+ const char* altTag = NULL;
+ if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) {
+ altTag = "view";
+ } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) {
+ startTag = "PreferenceScreen";
+ } else {
+ continue;
+ }
+
+ const KeyedVector<String8,sp<AaptGroup> > groups = d->getFiles();
const size_t N = groups.size();
for (size_t i=0; i<N; i++) {
const sp<AaptGroup>& group = groups.valueAt(i);
const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files = group->getFiles();
const size_t M = files.size();
for (size_t j=0; j<M; j++) {
- err = writeProguardForLayout(keep, files.valueAt(j));
+ err = writeProguardForXml(keep, files.valueAt(j), startTag, altTag);
if (err < 0) {
return err;
}