]> git.saurik.com Git - android/aapt.git/blobdiff - Resource.cpp
Fix issue #2482423: Settings is broken due to dead-code stripping
[android/aapt.git] / Resource.cpp
index 0d2ea60ad9af7e0efad9574580d59b18b0a6e430..9fcb21c417031c9273cc34420dd926758f263026 100644 (file)
@@ -101,13 +101,13 @@ public:
             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";
@@ -221,12 +221,12 @@ static status_t parsePackage(Bundle* bundle, const sp<AaptAssets>& assets,
            && 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);
                 }
             }
         }
@@ -562,9 +562,10 @@ void addTagAttribute(const sp<XMLNode>& node, const char* ns8,
     node->addAttribute(ns, attr, String16(value));
 }
 
-static void fullyQualifyClassName(String8& package, sp<XMLNode> node) {
+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"), String16("name"));
+            String16("http://schemas.android.com/apk/res/android"), attrName);
     if (attr != NULL) {
         String8 name(attr->string);
 
@@ -635,19 +636,40 @@ status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
         // Make class names fully qualified
         sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
         if (application != NULL) {
-            fullyQualifyClassName(origPackage, application);
+            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);
+                    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;
 }
 
@@ -1866,8 +1888,26 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass
     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;
@@ -1881,6 +1921,23 @@ writeProguardForLayout(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile)
 
     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;
@@ -1889,17 +1946,19 @@ writeProguardForLayout(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile)
 
         // 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());
+            }
         }
     }
 
@@ -1915,10 +1974,16 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
     for (size_t k=0; k<K; k++) {
         const sp<AaptDir>& d = dirs.itemAt(k);
         const String8& dirName = d->getLeaf();
-        if ((dirName != String8("layout")) && (strncmp(dirName.string(), "layout-", 7) != 0)) {
+        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++) {
@@ -1926,7 +1991,7 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
             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;
                 }