]> git.saurik.com Git - android/aapt.git/blobdiff - Resource.cpp
am 2606fc48: Reconcile with jb-mr0-release jb-release
[android/aapt.git] / Resource.cpp
index f64728d0a8c571ddbc9685fc3af7dce07af50fe5..ee076e602e5eee3ab0c0edad4ae47c71fdb71ac3 100644 (file)
 #include "FileFinder.h"
 #include "CacheUpdater.h"
 
+#include <utils/WorkQueue.h>
+
+#if HAVE_PRINTF_ZD
+#  define ZD "%zd"
+#  define ZD_TYPE ssize_t
+#else
+#  define ZD "%ld"
+#  define ZD_TYPE long
+#endif
+
 #define NOISY(x) // x
 
+// Number of threads to use for preprocessing images.
+static const size_t MAX_THREADS = 4;
+
 // ==========================================================================
 // ==========================================================================
 // ==========================================================================
@@ -158,9 +171,10 @@ private:
 
 bool isValidResourceType(const String8& type)
 {
-    return type == "anim" || type == "drawable" || type == "layout"
+    return type == "anim" || type == "animator" || type == "interpolator"
+        || type == "drawable" || type == "layout"
         || type == "values" || type == "xml" || type == "raw"
-        || type == "color" || type == "menu";
+        || type == "color" || type == "menu" || type == "mipmap";
 }
 
 static sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary=true)
@@ -293,21 +307,52 @@ static status_t makeFileResources(Bundle* bundle, const sp<AaptAssets>& assets,
     return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
 }
 
-static status_t preProcessImages(Bundle* bundle, const sp<AaptAssets>& assets,
-                          const sp<ResourceTypeSet>& set)
+class PreProcessImageWorkUnit : public WorkQueue::WorkUnit {
+public:
+    PreProcessImageWorkUnit(const Bundle* bundle, const sp<AaptAssets>& assets,
+            const sp<AaptFile>& file, volatile bool* hasErrors) :
+            mBundle(bundle), mAssets(assets), mFile(file), mHasErrors(hasErrors) {
+    }
+
+    virtual bool run() {
+        status_t status = preProcessImage(mBundle, mAssets, mFile, NULL);
+        if (status) {
+            *mHasErrors = true;
+        }
+        return true; // continue even if there are errors
+    }
+
+private:
+    const Bundle* mBundle;
+    sp<AaptAssets> mAssets;
+    sp<AaptFile> mFile;
+    volatile bool* mHasErrors;
+};
+
+static status_t preProcessImages(const Bundle* bundle, const sp<AaptAssets>& assets,
+                          const sp<ResourceTypeSet>& set, const char* type)
 {
-    bool hasErrors = false;
+    volatile bool hasErrors = false;
     ssize_t res = NO_ERROR;
     if (bundle->getUseCrunchCache() == false) {
-        ResourceDirIterator it(set, String8("drawable"));
-        Vector<sp<AaptFile> > newNameFiles;
-        Vector<String8> newNamePaths;
+        WorkQueue wq(MAX_THREADS, false);
+        ResourceDirIterator it(set, String8(type));
         while ((res=it.next()) == NO_ERROR) {
-            res = preProcessImage(bundle, assets, it.getFile(), NULL);
-            if (res < NO_ERROR) {
+            PreProcessImageWorkUnit* w = new PreProcessImageWorkUnit(
+                    bundle, assets, it.getFile(), &hasErrors);
+            status_t status = wq.schedule(w);
+            if (status) {
+                fprintf(stderr, "preProcessImages failed: schedule() returned %d\n", status);
                 hasErrors = true;
+                delete w;
+                break;
             }
         }
+        status_t status = wq.finish();
+        if (status) {
+            fprintf(stderr, "preProcessImages failed: finish() returned %d\n", status);
+            hasErrors = true;
+        }
     }
     return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
 }
@@ -351,18 +396,27 @@ static void collect_files(const sp<AaptDir>& dir,
 
         if (index < 0) {
             sp<ResourceTypeSet> set = new ResourceTypeSet();
+            NOISY(printf("Creating new resource type set for leaf %s with group %s (%p)\n",
+                    leafName.string(), group->getPath().string(), group.get()));
             set->add(leafName, group);
             resources->add(resType, set);
         } else {
             sp<ResourceTypeSet> set = resources->valueAt(index);
             index = set->indexOfKey(leafName);
             if (index < 0) {
+                NOISY(printf("Adding to resource type set for leaf %s group %s (%p)\n",
+                        leafName.string(), group->getPath().string(), group.get()));
                 set->add(leafName, group);
             } else {
                 sp<AaptGroup> existingGroup = set->valueAt(index);
-                int M = files.size();
-                for (int j=0; j<M; j++) {
-                    existingGroup->addFile(files.valueAt(j));
+                NOISY(printf("Extending to resource type set for leaf %s group %s (%p)\n",
+                        leafName.string(), group->getPath().string(), group.get()));
+                for (size_t j=0; j<files.size(); j++) {
+                    NOISY(printf("Adding file %s in group %s resType %s\n",
+                        files.valueAt(j)->getSourceFile().string(),
+                        files.keyAt(j).toDirName(String8()).string(),
+                        resType.string()));
+                    status_t err = existingGroup->addFile(files.valueAt(j));
                 }
             }
         }
@@ -377,9 +431,12 @@ static void collect_files(const sp<AaptAssets>& ass,
 
     for (int i=0; i<N; i++) {
         sp<AaptDir> d = dirs.itemAt(i);
+        NOISY(printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
+                d->getLeaf().string()));
         collect_files(d, resources);
 
         // don't try to include the res dir
+        NOISY(printf("Removing dir leaf %s\n", d->getLeaf().string()));
         ass->removeDir(d->getLeaf());
     }
 }
@@ -553,11 +610,11 @@ static bool applyFileOverlay(Bundle *bundle,
                         DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
                                 baseGroup->getFiles();
                         for (size_t i=0; i < baseFiles.size(); i++) {
-                            printf("baseFile %ld has flavor %s\n", i,
+                            printf("baseFile " ZD " has flavor %s\n", (ZD_TYPE) i,
                                     baseFiles.keyAt(i).toString().string());
                         }
                         for (size_t i=0; i < overlayFiles.size(); i++) {
-                            printf("overlayFile %ld has flavor %s\n", i,
+                            printf("overlayFile " ZD " has flavor %s\n", (ZD_TYPE) i,
                                     overlayFiles.keyAt(i).toString().string());
                         }
                     }
@@ -569,16 +626,21 @@ static bool applyFileOverlay(Bundle *bundle,
                         size_t baseFileIndex =
                                 baseGroup->getFiles().indexOfKey(overlayFiles.
                                 keyAt(overlayGroupIndex));
-                        if(baseFileIndex < UNKNOWN_ERROR) {
+                        if (baseFileIndex < UNKNOWN_ERROR) {
                             if (bundle->getVerbose()) {
-                                printf("found a match (%ld) for overlay file %s, for flavor %s\n",
-                                        baseFileIndex,
+                                printf("found a match (" ZD ") for overlay file %s, for flavor %s\n",
+                                        (ZD_TYPE) baseFileIndex,
                                         overlayGroup->getLeaf().string(),
                                         overlayFiles.keyAt(overlayGroupIndex).toString().string());
                             }
                             baseGroup->removeFile(baseFileIndex);
                         } else {
                             // didn't find a match fall through and add it..
+                            if (true || bundle->getVerbose()) {
+                                printf("nothing matches overlay file %s, for flavor %s\n",
+                                        overlayGroup->getLeaf().string(),
+                                        overlayFiles.keyAt(overlayGroupIndex).toString().string());
+                            }
                         }
                         baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex));
                         assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
@@ -821,8 +883,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
      * request UTF-16 encoding and the parameters of this package
      * allow UTF-8 to be used.
      */
-    if (!bundle->getWantUTF16()
-            && bundle->isMinSdkAtLeast(SDK_FROYO)) {
+    if (!bundle->getUTF16StringsOption()) {
         xmlFlags |= XML_COMPILE_UTF8;
     }
 
@@ -838,18 +899,24 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
     sp<ResourceTypeSet> drawables;
     sp<ResourceTypeSet> layouts;
     sp<ResourceTypeSet> anims;
+    sp<ResourceTypeSet> animators;
+    sp<ResourceTypeSet> interpolators;
     sp<ResourceTypeSet> xmls;
     sp<ResourceTypeSet> raws;
     sp<ResourceTypeSet> colors;
     sp<ResourceTypeSet> menus;
+    sp<ResourceTypeSet> mipmaps;
 
     ASSIGN_IT(drawable);
     ASSIGN_IT(layout);
     ASSIGN_IT(anim);
+    ASSIGN_IT(animator);
+    ASSIGN_IT(interpolator);
     ASSIGN_IT(xml);
     ASSIGN_IT(raw);
     ASSIGN_IT(color);
     ASSIGN_IT(menu);
+    ASSIGN_IT(mipmap);
 
     assets->setResources(resources);
     // now go through any resource overlays and collect their files
@@ -865,10 +932,13 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
     if (!applyFileOverlay(bundle, assets, &drawables, "drawable") ||
             !applyFileOverlay(bundle, assets, &layouts, "layout") ||
             !applyFileOverlay(bundle, assets, &anims, "anim") ||
+            !applyFileOverlay(bundle, assets, &animators, "animator") ||
+            !applyFileOverlay(bundle, assets, &interpolators, "interpolator") ||
             !applyFileOverlay(bundle, assets, &xmls, "xml") ||
             !applyFileOverlay(bundle, assets, &raws, "raw") ||
             !applyFileOverlay(bundle, assets, &colors, "color") ||
-            !applyFileOverlay(bundle, assets, &menus, "menu")) {
+            !applyFileOverlay(bundle, assets, &menus, "menu") ||
+            !applyFileOverlay(bundle, assets, &mipmaps, "mipmap")) {
         return UNKNOWN_ERROR;
     }
 
@@ -876,7 +946,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
 
     if (drawables != NULL) {
         if (bundle->getOutputAPKFile() != NULL) {
-            err = preProcessImages(bundle, assets, drawables);
+            err = preProcessImages(bundle, assets, drawables, "drawable");
         }
         if (err == NO_ERROR) {
             err = makeFileResources(bundle, assets, &table, drawables, "drawable");
@@ -888,6 +958,20 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
         }
     }
 
+    if (mipmaps != NULL) {
+        if (bundle->getOutputAPKFile() != NULL) {
+            err = preProcessImages(bundle, assets, mipmaps, "mipmap");
+        }
+        if (err == NO_ERROR) {
+            err = makeFileResources(bundle, assets, &table, mipmaps, "mipmap");
+            if (err != NO_ERROR) {
+                hasErrors = true;
+            }
+        } else {
+            hasErrors = true;
+        }
+    }
+
     if (layouts != NULL) {
         err = makeFileResources(bundle, assets, &table, layouts, "layout");
         if (err != NO_ERROR) {
@@ -902,6 +986,20 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
         }
     }
 
+    if (animators != NULL) {
+        err = makeFileResources(bundle, assets, &table, animators, "animator");
+        if (err != NO_ERROR) {
+            hasErrors = true;
+        }
+    }
+
+    if (interpolators != NULL) {
+        err = makeFileResources(bundle, assets, &table, interpolators, "interpolator");
+        if (err != NO_ERROR) {
+            hasErrors = true;
+        }
+    }
+
     if (xmls != NULL) {
         err = makeFileResources(bundle, assets, &table, xmls, "xml");
         if (err != NO_ERROR) {
@@ -1009,6 +1107,36 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
         err = NO_ERROR;
     }
 
+    if (animators != NULL) {
+        ResourceDirIterator it(animators, String8("animator"));
+        while ((err=it.next()) == NO_ERROR) {
+            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            if (err != NO_ERROR) {
+                hasErrors = true;
+            }
+        }
+
+        if (err < NO_ERROR) {
+            hasErrors = true;
+        }
+        err = NO_ERROR;
+    }
+
+    if (interpolators != NULL) {
+        ResourceDirIterator it(interpolators, String8("interpolator"));
+        while ((err=it.next()) == NO_ERROR) {
+            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            if (err != NO_ERROR) {
+                hasErrors = true;
+            }
+        }
+
+        if (err < NO_ERROR) {
+            hasErrors = true;
+        }
+        err = NO_ERROR;
+    }
+
     if (xmls != NULL) {
         ResourceDirIterator it(xmls, String8("xml"));
         while ((err=it.next()) == NO_ERROR) {
@@ -1716,7 +1844,7 @@ static status_t writeSymbolClass(
         if (sym.typeCode != AaptSymbolEntry::TYPE_INT32) {
             continue;
         }
-        if (!includePrivate && !sym.isPublic) {
+        if (!assets->isJavaSymbol(sym, includePrivate)) {
             continue;
         }
         String16 name(sym.name);
@@ -1772,7 +1900,7 @@ static status_t writeSymbolClass(
         if (sym.typeCode != AaptSymbolEntry::TYPE_STRING) {
             continue;
         }
-        if (!includePrivate && !sym.isPublic) {
+        if (!assets->isJavaSymbol(sym, includePrivate)) {
             continue;
         }
         String16 name(sym.name);
@@ -1884,7 +2012,8 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets,
         "\n"
         "package %s;\n\n", package.string());
 
-        status_t err = writeSymbolClass(fp, assets, includePrivate, symbols, className, 0, bundle->getNonConstantId());
+        status_t err = writeSymbolClass(fp, assets, includePrivate, symbols,
+                className, 0, bundle->getNonConstantId());
         if (err != NO_ERROR) {
             return err;
         }
@@ -1960,6 +2089,23 @@ addProguardKeepRule(ProguardKeepSet* keep, const String8& inClassName,
     keep->add(rule, location);
 }
 
+void
+addProguardKeepMethodRule(ProguardKeepSet* keep, const String8& memberName,
+        const char* pkg, const String8& srcName, int line)
+{
+    String8 rule("-keepclassmembers class * { *** ");
+    rule += memberName;
+    rule += "(...); }";
+
+    String8 location("onClick ");
+    location += srcName;
+    char lineno[20];
+    sprintf(lineno, ":%d", line);
+    location += lineno;
+
+    keep->add(rule, location);
+}
+
 status_t
 writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
 {
@@ -2064,7 +2210,7 @@ struct NamespaceAttributePair {
 
 status_t
 writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile,
-        const char* startTag, const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs)
+        const char* startTag, const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs)
 {
     status_t err;
     ResXMLTree tree;
@@ -2108,28 +2254,48 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile,
         } else if (tagAttrPairs != NULL) {
             ssize_t tagIndex = tagAttrPairs->indexOfKey(tag);
             if (tagIndex >= 0) {
-                const NamespaceAttributePair& nsAttr = tagAttrPairs->valueAt(tagIndex);
-                ssize_t attrIndex = tree.indexOfAttribute(nsAttr.ns, nsAttr.attr);
-                if (attrIndex < 0) {
-                    // fprintf(stderr, "%s:%d: <%s> does not have attribute %s:%s.\n",
-                    //        layoutFile->getPrintableSource().string(), tree.getLineNumber(),
-                    //        tag.string(), nsAttr.ns, nsAttr.attr);
-                } else {
-                    size_t len;
-                    addProguardKeepRule(keep,
-                                        String8(tree.getAttributeStringValue(attrIndex, &len)), NULL,
-                                        layoutFile->getPrintableSource(), tree.getLineNumber());
+                const Vector<NamespaceAttributePair>& nsAttrVector = tagAttrPairs->valueAt(tagIndex);
+                for (size_t i = 0; i < nsAttrVector.size(); i++) {
+                    const NamespaceAttributePair& nsAttr = nsAttrVector[i];
+
+                    ssize_t attrIndex = tree.indexOfAttribute(nsAttr.ns, nsAttr.attr);
+                    if (attrIndex < 0) {
+                        // fprintf(stderr, "%s:%d: <%s> does not have attribute %s:%s.\n",
+                        //        layoutFile->getPrintableSource().string(), tree.getLineNumber(),
+                        //        tag.string(), nsAttr.ns, nsAttr.attr);
+                    } else {
+                        size_t len;
+                        addProguardKeepRule(keep,
+                                            String8(tree.getAttributeStringValue(attrIndex, &len)), NULL,
+                                            layoutFile->getPrintableSource(), tree.getLineNumber());
+                    }
                 }
             }
         }
+        ssize_t attrIndex = tree.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "onClick");
+        if (attrIndex >= 0) {
+            size_t len;
+            addProguardKeepMethodRule(keep,
+                                String8(tree.getAttributeStringValue(attrIndex, &len)), NULL,
+                                layoutFile->getPrintableSource(), tree.getLineNumber());
+        }
     }
 
     return NO_ERROR;
 }
 
-static void addTagAttrPair(KeyedVector<String8, NamespaceAttributePair>* dest,
+static void addTagAttrPair(KeyedVector<String8, Vector<NamespaceAttributePair> >* dest,
         const char* tag, const char* ns, const char* attr) {
-    dest->add(String8(tag), NamespaceAttributePair(ns, attr));
+    String8 tagStr(tag);
+    ssize_t index = dest->indexOfKey(tagStr);
+
+    if (index < 0) {
+        Vector<NamespaceAttributePair> vector;
+        vector.add(NamespaceAttributePair(ns, attr));
+        dest->add(tagStr, vector);
+    } else {
+        dest->editValueAt(index).add(NamespaceAttributePair(ns, attr));
+    }
 }
 
 status_t
@@ -2138,14 +2304,15 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
     status_t err;
 
     // tag:attribute pairs that should be checked in layout files.
-    KeyedVector<String8, NamespaceAttributePair> kLayoutTagAttrPairs;
+    KeyedVector<String8, Vector<NamespaceAttributePair> > kLayoutTagAttrPairs;
     addTagAttrPair(&kLayoutTagAttrPairs, "view", NULL, "class");
+    addTagAttrPair(&kLayoutTagAttrPairs, "fragment", NULL, "class");
     addTagAttrPair(&kLayoutTagAttrPairs, "fragment", RESOURCES_ANDROID_NAMESPACE, "name");
 
     // tag:attribute pairs that should be checked in xml files.
-    KeyedVector<String8, NamespaceAttributePair> kXmlTagAttrPairs;
+    KeyedVector<String8, Vector<NamespaceAttributePair> > kXmlTagAttrPairs;
     addTagAttrPair(&kXmlTagAttrPairs, "PreferenceScreen", RESOURCES_ANDROID_NAMESPACE, "fragment");
-    addTagAttrPair(&kXmlTagAttrPairs, "Header", RESOURCES_ANDROID_NAMESPACE, "fragment");
+    addTagAttrPair(&kXmlTagAttrPairs, "header", RESOURCES_ANDROID_NAMESPACE, "fragment");
 
     const Vector<sp<AaptDir> >& dirs = assets->resDirs();
     const size_t K = dirs.size();
@@ -2153,12 +2320,15 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
         const sp<AaptDir>& d = dirs.itemAt(k);
         const String8& dirName = d->getLeaf();
         const char* startTag = NULL;
-        const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs = NULL;
+        const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs = NULL;
         if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) {
             tagAttrPairs = &kLayoutTagAttrPairs;
         } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) {
             startTag = "PreferenceScreen";
             tagAttrPairs = &kXmlTagAttrPairs;
+        } else if ((dirName == String8("menu")) || (strncmp(dirName.string(), "menu-", 5) == 0)) {
+            startTag = "menu";
+            tagAttrPairs = NULL;
         } else {
             continue;
         }
@@ -2177,6 +2347,12 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
             }
         }
     }
+    // Handle the overlays
+    sp<AaptAssets> overlay = assets->getOverlay();
+    if (overlay.get()) {
+        return writeProguardForLayouts(keep, overlay);
+    }
+
     return NO_ERROR;
 }