]> git.saurik.com Git - android/aapt.git/commitdiff
Allow overlays to add resources.
authorDianne Hackborn <hackbod@google.com>
Thu, 13 Aug 2009 20:36:00 +0000 (13:36 -0700)
committerDianne Hackborn <hackbod@google.com>
Thu, 13 Aug 2009 20:36:00 +0000 (13:36 -0700)
Resource.cpp
ResourceTable.cpp
ResourceTable.h

index 41ee88b4451c1bc90162a62f4b5883262c32cd25..9d2ed1044b3eb30e4d57104dc165ee8aa9be342a 100644 (file)
@@ -475,10 +475,8 @@ static bool applyFileOverlay(const sp<AaptAssets>& assets,
                     }
                 } 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;
+                    baseSet->add(overlaySet->keyAt(overlayIndex),
+                            overlaySet->valueAt(overlayIndex));
                 }
             }
             // this overlay didn't have resources for this type
index 8dbc12ec6069a45d3a3b0f3ccc6a2683cd73ec3b..95a238401832e78941f045652788cc9950378c80 100644 (file)
@@ -663,6 +663,7 @@ status_t compileResourceFile(Bundle* bundle,
     const String16 public16("public");
     const String16 public_padding16("public-padding");
     const String16 private_symbols16("private-symbols");
+    const String16 add_resource16("add-resource");
     const String16 skip16("skip");
     const String16 eat_comment16("eat-comment");
 
@@ -960,6 +961,36 @@ status_t compileResourceFile(Bundle* bundle,
                 }
                 continue;
 
+            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
+                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+            
+                String16 typeName;
+                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
+                if (typeIdx < 0) {
+                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
+                    hasErrors = localHasErrors = true;
+                }
+                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
+
+                String16 name;
+                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+                if (nameIdx < 0) {
+                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
+                    hasErrors = localHasErrors = true;
+                }
+                name = String16(block.getAttributeStringValue(nameIdx, &len));
+
+                outTable->canAddEntry(srcPos, myPackage, typeName, name);
+
+                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+                    if (code == ResXMLTree::END_TAG) {
+                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
+                            break;
+                        }
+                    }
+                }
+                continue;
+                
             } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
                 SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
                                 
@@ -1557,9 +1588,21 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos,
     }
 #endif
     if (overlay && !hasBagOrEntry(package, type, name)) {
-        sourcePos.error("Can't add new bags in an overlay.  See '%s'\n",
-                        String8(name).string());
-        return UNKNOWN_ERROR;
+        bool canAdd = false;
+        sp<Package> p = mPackages.valueFor(package);
+        if (p != NULL) {
+            sp<Type> t = p->getTypes().valueFor(type);
+            if (t != NULL) {
+                if (t->getCanAddEntries().indexOf(name) >= 0) {
+                    canAdd = true;
+                }
+            }
+        }
+        if (!canAdd) {
+            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
+                            String8(name).string());
+            return UNKNOWN_ERROR;
+        }
     }
     sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
     if (e == NULL) {
@@ -1724,6 +1767,15 @@ bool ResourceTable::appendTypeComment(const String16& package,
     return false;
 }
 
+void ResourceTable::canAddEntry(const SourcePos& pos,
+        const String16& package, const String16& type, const String16& name)
+{
+    sp<Type> t = getType(package, type, pos);
+    if (t != NULL) {
+        t->canAddEntry(name);
+    }
+}
+
 size_t ResourceTable::size() const {
     return mPackages.size();
 }
@@ -3215,6 +3267,11 @@ status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos,
     return NO_ERROR;
 }
 
+void ResourceTable::Type::canAddEntry(const String16& name)
+{
+    mCanAddEntries.add(name);
+}
+
 sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
                                                        const SourcePos& sourcePos,
                                                        const ResTable_config* config,
@@ -3224,9 +3281,10 @@ sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
     int pos = -1;
     sp<ConfigList> c = mConfigs.valueFor(entry);
     if (c == NULL) {
-        if (overlay == true) {
-            sourcePos.error("Resource %s appears in overlay but not"
-                            " in the base package.\n", String8(entry).string());
+        if (overlay == true && mCanAddEntries.indexOf(entry) < 0) {
+            sourcePos.error("Resource at %s appears in overlay but not"
+                            " in the base package; use <add-resource> to add.\n",
+                            String8(entry).string());
             return NULL;
         }
         c = new ConfigList(entry, sourcePos);
index ec4331aa35579b600151fbfc0acce0d6c86e667c..caa01b3f472f04250360fa255f5c00573d526dc2 100644 (file)
@@ -132,6 +132,9 @@ public:
                            const String16& name,
                            const String16& comment);
     
+    void canAddEntry(const SourcePos& pos,
+        const String16& package, const String16& type, const String16& name);
+        
     size_t size() const;
     size_t numLocalResources() const;
     bool hasResources() const;
@@ -413,7 +416,9 @@ public:
         status_t addPublic(const SourcePos& pos,
                            const String16& name,
                            const uint32_t ident);
-
+                           
+        void canAddEntry(const String16& name);
+        
         String16 getName() const { return mName; }
         sp<Entry> getEntry(const String16& entry,
                            const SourcePos& pos,
@@ -435,6 +440,8 @@ public:
         const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
         const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
 
+        const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; }
+        
         const SourcePos& getPos() const { return mPos; }
     private:
         String16 mName;
@@ -443,6 +450,7 @@ public:
         SortedVector<ConfigDescription> mUniqueConfigs;
         DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
         Vector<sp<ConfigList> > mOrderedConfigs;
+        SortedVector<String16> mCanAddEntries;
         int32_t mPublicIndex;
         int32_t mIndex;
         SourcePos mPos;