Loading tools/aapt/Resource.cpp +1 −8 Original line number Diff line number Diff line Loading @@ -1537,14 +1537,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil std::queue<CompileResourceWorkItem>& workQueue = table.getWorkQueue(); while (!workQueue.empty()) { CompileResourceWorkItem& workItem = workQueue.front(); if (workItem.xmlRoot != NULL) { err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.xmlRoot, workItem.file, &table, xmlFlags); } else { err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags); } err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags); if (err == NO_ERROR) { assets->addResource(workItem.resPath.getPathLeaf(), workItem.resPath, Loading tools/aapt/ResourceTable.cpp +3 −230 Original line number Diff line number Diff line Loading @@ -88,11 +88,8 @@ status_t compileXmlFile(const Bundle* bundle, root->setUTF8(true); } if (table->processBundleFormat(bundle, resourceName, target, root) != NO_ERROR) { return UNKNOWN_ERROR; } bool hasErrors = false; if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) { status_t err = root->assignResourceIds(assets, table); if (err != NO_ERROR) { Loading Loading @@ -4758,9 +4755,9 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, newConfig.sdkVersion = sdkVersionToGenerate; sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), AaptGroupEntry(newConfig), target->getResourceType()); String8 resPath = String8::format("res/%s/%s.xml", String8 resPath = String8::format("res/%s/%s", newFile->getGroupEntry().toDirName(target->getResourceType()).string(), String8(resourceName).string()); target->getSourceFile().getPathLeaf().string()); resPath.convertToResPath(); // Add a resource table entry. Loading @@ -4787,7 +4784,6 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, item.resourceName = resourceName; item.resPath = resPath; item.file = newFile; item.xmlRoot = newRoot; mWorkQueue.push(item); } Loading Loading @@ -4829,226 +4825,3 @@ void ResourceTable::getDensityVaryingResources( } } } static String16 buildNamespace(const String16& package) { return String16("http://schemas.android.com/apk/res/") + package; } static sp<XMLNode> findOnlyChildElement(const sp<XMLNode>& parent) { const Vector<sp<XMLNode> >& children = parent->getChildren(); sp<XMLNode> onlyChild; for (size_t i = 0; i < children.size(); i++) { if (children[i]->getType() != XMLNode::TYPE_CDATA) { if (onlyChild != NULL) { return NULL; } onlyChild = children[i]; } } return onlyChild; } /** * Detects use of the `bundle' format and extracts nested resources into their own top level * resources. The bundle format looks like this: * * <!-- res/drawable/bundle.xml --> * <animated-vector xmlns:aapt="http://schemas.android.com/aapt"> * <aapt:attr name="android:drawable"> * <vector android:width="60dp" * android:height="60dp"> * <path android:name="v" * android:fillColor="#000000" * android:pathData="M300,70 l 0,-70 70,..." /> * </vector> * </aapt:attr> * </animated-vector> * * When AAPT sees the <aapt:attr> tag, it will extract its single element and its children * into a new high-level resource, assigning it a name and ID. Then value of the `name` * attribute must be a resource attribute. That resource attribute is inserted into the parent * with the reference to the extracted resource as the value. * * <!-- res/drawable/bundle.xml --> * <animated-vector android:drawable="@drawable/bundle_1.xml"> * </animated-vector> * * <!-- res/drawable/bundle_1.xml --> * <vector android:width="60dp" * android:height="60dp"> * <path android:name="v" * android:fillColor="#000000" * android:pathData="M300,70 l 0,-70 70,..." /> * </vector> */ status_t ResourceTable::processBundleFormat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, const sp<XMLNode>& root) { Vector<sp<XMLNode> > namespaces; if (root->getType() == XMLNode::TYPE_NAMESPACE) { namespaces.push(root); } return processBundleFormatImpl(bundle, resourceName, target, root, &namespaces); } status_t ResourceTable::processBundleFormatImpl(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, const sp<XMLNode>& parent, Vector<sp<XMLNode> >* namespaces) { const String16 kAaptNamespaceUri16("http://schemas.android.com/aapt"); const String16 kName16("name"); const String16 kAttr16("attr"); const String16 kAssetPackage16(mAssets->getPackage()); Vector<sp<XMLNode> >& children = parent->getChildren(); for (size_t i = 0; i < children.size(); i++) { const sp<XMLNode>& child = children[i]; if (child->getType() == XMLNode::TYPE_CDATA) { continue; } else if (child->getType() == XMLNode::TYPE_NAMESPACE) { namespaces->push(child); } if (child->getElementNamespace() != kAaptNamespaceUri16 || child->getElementName() != kAttr16) { status_t result = processBundleFormatImpl(bundle, resourceName, target, child, namespaces); if (result != NO_ERROR) { return result; } if (child->getType() == XMLNode::TYPE_NAMESPACE) { namespaces->pop(); } continue; } // This is the <aapt:attr> tag. Look for the 'name' attribute. SourcePos source(child->getFilename(), child->getStartLineNumber()); sp<XMLNode> nestedRoot = findOnlyChildElement(child); if (nestedRoot == NULL) { source.error("<%s:%s> must have exactly one child element", String8(child->getElementNamespace()).string(), String8(child->getElementName()).string()); return UNKNOWN_ERROR; } // Find the special attribute 'parent-attr'. This attribute's value contains // the resource attribute for which this element should be assigned in the parent. const XMLNode::attribute_entry* attr = child->getAttribute(String16(), kName16); if (attr == NULL) { source.error("inline resource definition must specify an attribute via 'name'"); return UNKNOWN_ERROR; } // Parse the attribute name. const char* errorMsg = NULL; String16 attrPackage, attrType, attrName; bool result = ResTable::expandResourceRef(attr->string.string(), attr->string.size(), &attrPackage, &attrType, &attrName, &kAttr16, &kAssetPackage16, &errorMsg, NULL); if (!result) { source.error("invalid attribute name for 'name': %s", errorMsg); return UNKNOWN_ERROR; } if (attrType != kAttr16) { // The value of the 'name' attribute must be an attribute reference. source.error("value of 'name' must be an attribute reference."); return UNKNOWN_ERROR; } // Generate a name for this nested resource and try to add it to the table. // We do this in a loop because the name may be taken, in which case we will // increment a suffix until we succeed. String8 nestedResourceName; String8 nestedResourcePath; int suffix = 1; while (true) { // This child element will be extracted into its own resource file. // Generate a name and path for it from its parent. nestedResourceName = String8::format("%s_%d", String8(resourceName).string(), suffix++); nestedResourcePath = String8::format("res/%s/%s.xml", target->getGroupEntry().toDirName(target->getResourceType()) .string(), nestedResourceName.string()); // Lookup or create the entry for this name. sp<Entry> entry = getEntry(kAssetPackage16, String16(target->getResourceType()), String16(nestedResourceName), source, false, &target->getGroupEntry().toParams(), true); if (entry == NULL) { return UNKNOWN_ERROR; } if (entry->getType() == Entry::TYPE_UNKNOWN) { // The value for this resource has never been set, // meaning we're good! entry->setItem(source, String16(nestedResourcePath)); break; } // We failed (name already exists), so try with a different name // (increment the suffix). } if (bundle->getVerbose()) { source.printf("generating nested resource %s:%s/%s", mAssets->getPackage().string(), target->getResourceType().string(), nestedResourceName.string()); } // Build the attribute reference and assign it to the parent. String16 nestedResourceRef = String16(String8::format("@%s:%s/%s", mAssets->getPackage().string(), target->getResourceType().string(), nestedResourceName.string())); String16 attrNs = buildNamespace(attrPackage); if (parent->getAttribute(attrNs, attrName) != NULL) { SourcePos(parent->getFilename(), parent->getStartLineNumber()) .error("parent of nested resource already defines attribute '%s:%s'", String8(attrPackage).string(), String8(attrName).string()); return UNKNOWN_ERROR; } // Add the reference to the inline resource. parent->addAttribute(attrNs, attrName, nestedResourceRef); // Remove the <aapt:attr> child element from here. children.removeAt(i); i--; // Append all namespace declarations that we've seen on this branch in the XML tree // to this resource. // We do this because the order of namespace declarations and prefix usage is determined // by the developer and we do not want to override any decisions. Be conservative. for (size_t nsIndex = namespaces->size(); nsIndex > 0; nsIndex--) { const sp<XMLNode>& ns = namespaces->itemAt(nsIndex - 1); sp<XMLNode> newNs = XMLNode::newNamespace(ns->getFilename(), ns->getNamespacePrefix(), ns->getNamespaceUri()); newNs->addChild(nestedRoot); nestedRoot = newNs; } // Schedule compilation of the nested resource. CompileResourceWorkItem workItem; workItem.resPath = nestedResourcePath; workItem.resourceName = String16(nestedResourceName); workItem.xmlRoot = nestedRoot; workItem.file = new AaptFile(target->getSourceFile(), target->getGroupEntry(), target->getResourceType()); mWorkQueue.push(workItem); } return NO_ERROR; } tools/aapt/ResourceTable.h +0 −12 Original line number Diff line number Diff line Loading @@ -83,7 +83,6 @@ struct CompileResourceWorkItem { String16 resourceName; String8 resPath; sp<AaptFile> file; sp<XMLNode> xmlRoot; }; class ResourceTable : public ResTable::Accessor Loading Loading @@ -207,12 +206,6 @@ public: const sp<AaptFile>& file, const sp<XMLNode>& root); status_t processBundleFormat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& file, const sp<XMLNode>& parent); sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const bool isBase); Loading Loading @@ -593,11 +586,6 @@ private: Res_value* outValue); int getPublicAttributeSdkLevel(uint32_t attrId) const; status_t processBundleFormatImpl(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& file, const sp<XMLNode>& parent, Vector<sp<XMLNode> >* namespaces); String16 mAssetsPackage; PackageType mPackageType; Loading tools/aapt/XMLNode.cpp +0 −18 Original line number Diff line number Diff line Loading @@ -693,12 +693,6 @@ const Vector<sp<XMLNode> >& XMLNode::getChildren() const return mChildren; } Vector<sp<XMLNode> >& XMLNode::getChildren() { return mChildren; } const String8& XMLNode::getFilename() const { return mFilename; Loading @@ -723,18 +717,6 @@ const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns, return NULL; } bool XMLNode::removeAttribute(const String16& ns, const String16& name) { for (size_t i = 0; i < mAttributes.size(); i++) { const attribute_entry& ae(mAttributes.itemAt(i)); if (ae.ns == ns && ae.name == name) { removeAttribute(i); return true; } } return false; } XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns, const String16& name) { Loading tools/aapt/XMLNode.h +1 −3 Original line number Diff line number Diff line Loading @@ -70,7 +70,6 @@ public: const String16& getElementNamespace() const; const String16& getElementName() const; const Vector<sp<XMLNode> >& getChildren() const; Vector<sp<XMLNode> >& getChildren(); const String8& getFilename() const; Loading Loading @@ -98,7 +97,6 @@ public: const Vector<attribute_entry>& getAttributes() const; const attribute_entry* getAttribute(const String16& ns, const String16& name) const; bool removeAttribute(const String16& ns, const String16& name); attribute_entry* editAttribute(const String16& ns, const String16& name); Loading Loading
tools/aapt/Resource.cpp +1 −8 Original line number Diff line number Diff line Loading @@ -1537,14 +1537,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil std::queue<CompileResourceWorkItem>& workQueue = table.getWorkQueue(); while (!workQueue.empty()) { CompileResourceWorkItem& workItem = workQueue.front(); if (workItem.xmlRoot != NULL) { err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.xmlRoot, workItem.file, &table, xmlFlags); } else { err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags); } err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags); if (err == NO_ERROR) { assets->addResource(workItem.resPath.getPathLeaf(), workItem.resPath, Loading
tools/aapt/ResourceTable.cpp +3 −230 Original line number Diff line number Diff line Loading @@ -88,11 +88,8 @@ status_t compileXmlFile(const Bundle* bundle, root->setUTF8(true); } if (table->processBundleFormat(bundle, resourceName, target, root) != NO_ERROR) { return UNKNOWN_ERROR; } bool hasErrors = false; if ((options&XML_COMPILE_ASSIGN_ATTRIBUTE_IDS) != 0) { status_t err = root->assignResourceIds(assets, table); if (err != NO_ERROR) { Loading Loading @@ -4758,9 +4755,9 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, newConfig.sdkVersion = sdkVersionToGenerate; sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), AaptGroupEntry(newConfig), target->getResourceType()); String8 resPath = String8::format("res/%s/%s.xml", String8 resPath = String8::format("res/%s/%s", newFile->getGroupEntry().toDirName(target->getResourceType()).string(), String8(resourceName).string()); target->getSourceFile().getPathLeaf().string()); resPath.convertToResPath(); // Add a resource table entry. Loading @@ -4787,7 +4784,6 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, item.resourceName = resourceName; item.resPath = resPath; item.file = newFile; item.xmlRoot = newRoot; mWorkQueue.push(item); } Loading Loading @@ -4829,226 +4825,3 @@ void ResourceTable::getDensityVaryingResources( } } } static String16 buildNamespace(const String16& package) { return String16("http://schemas.android.com/apk/res/") + package; } static sp<XMLNode> findOnlyChildElement(const sp<XMLNode>& parent) { const Vector<sp<XMLNode> >& children = parent->getChildren(); sp<XMLNode> onlyChild; for (size_t i = 0; i < children.size(); i++) { if (children[i]->getType() != XMLNode::TYPE_CDATA) { if (onlyChild != NULL) { return NULL; } onlyChild = children[i]; } } return onlyChild; } /** * Detects use of the `bundle' format and extracts nested resources into their own top level * resources. The bundle format looks like this: * * <!-- res/drawable/bundle.xml --> * <animated-vector xmlns:aapt="http://schemas.android.com/aapt"> * <aapt:attr name="android:drawable"> * <vector android:width="60dp" * android:height="60dp"> * <path android:name="v" * android:fillColor="#000000" * android:pathData="M300,70 l 0,-70 70,..." /> * </vector> * </aapt:attr> * </animated-vector> * * When AAPT sees the <aapt:attr> tag, it will extract its single element and its children * into a new high-level resource, assigning it a name and ID. Then value of the `name` * attribute must be a resource attribute. That resource attribute is inserted into the parent * with the reference to the extracted resource as the value. * * <!-- res/drawable/bundle.xml --> * <animated-vector android:drawable="@drawable/bundle_1.xml"> * </animated-vector> * * <!-- res/drawable/bundle_1.xml --> * <vector android:width="60dp" * android:height="60dp"> * <path android:name="v" * android:fillColor="#000000" * android:pathData="M300,70 l 0,-70 70,..." /> * </vector> */ status_t ResourceTable::processBundleFormat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, const sp<XMLNode>& root) { Vector<sp<XMLNode> > namespaces; if (root->getType() == XMLNode::TYPE_NAMESPACE) { namespaces.push(root); } return processBundleFormatImpl(bundle, resourceName, target, root, &namespaces); } status_t ResourceTable::processBundleFormatImpl(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, const sp<XMLNode>& parent, Vector<sp<XMLNode> >* namespaces) { const String16 kAaptNamespaceUri16("http://schemas.android.com/aapt"); const String16 kName16("name"); const String16 kAttr16("attr"); const String16 kAssetPackage16(mAssets->getPackage()); Vector<sp<XMLNode> >& children = parent->getChildren(); for (size_t i = 0; i < children.size(); i++) { const sp<XMLNode>& child = children[i]; if (child->getType() == XMLNode::TYPE_CDATA) { continue; } else if (child->getType() == XMLNode::TYPE_NAMESPACE) { namespaces->push(child); } if (child->getElementNamespace() != kAaptNamespaceUri16 || child->getElementName() != kAttr16) { status_t result = processBundleFormatImpl(bundle, resourceName, target, child, namespaces); if (result != NO_ERROR) { return result; } if (child->getType() == XMLNode::TYPE_NAMESPACE) { namespaces->pop(); } continue; } // This is the <aapt:attr> tag. Look for the 'name' attribute. SourcePos source(child->getFilename(), child->getStartLineNumber()); sp<XMLNode> nestedRoot = findOnlyChildElement(child); if (nestedRoot == NULL) { source.error("<%s:%s> must have exactly one child element", String8(child->getElementNamespace()).string(), String8(child->getElementName()).string()); return UNKNOWN_ERROR; } // Find the special attribute 'parent-attr'. This attribute's value contains // the resource attribute for which this element should be assigned in the parent. const XMLNode::attribute_entry* attr = child->getAttribute(String16(), kName16); if (attr == NULL) { source.error("inline resource definition must specify an attribute via 'name'"); return UNKNOWN_ERROR; } // Parse the attribute name. const char* errorMsg = NULL; String16 attrPackage, attrType, attrName; bool result = ResTable::expandResourceRef(attr->string.string(), attr->string.size(), &attrPackage, &attrType, &attrName, &kAttr16, &kAssetPackage16, &errorMsg, NULL); if (!result) { source.error("invalid attribute name for 'name': %s", errorMsg); return UNKNOWN_ERROR; } if (attrType != kAttr16) { // The value of the 'name' attribute must be an attribute reference. source.error("value of 'name' must be an attribute reference."); return UNKNOWN_ERROR; } // Generate a name for this nested resource and try to add it to the table. // We do this in a loop because the name may be taken, in which case we will // increment a suffix until we succeed. String8 nestedResourceName; String8 nestedResourcePath; int suffix = 1; while (true) { // This child element will be extracted into its own resource file. // Generate a name and path for it from its parent. nestedResourceName = String8::format("%s_%d", String8(resourceName).string(), suffix++); nestedResourcePath = String8::format("res/%s/%s.xml", target->getGroupEntry().toDirName(target->getResourceType()) .string(), nestedResourceName.string()); // Lookup or create the entry for this name. sp<Entry> entry = getEntry(kAssetPackage16, String16(target->getResourceType()), String16(nestedResourceName), source, false, &target->getGroupEntry().toParams(), true); if (entry == NULL) { return UNKNOWN_ERROR; } if (entry->getType() == Entry::TYPE_UNKNOWN) { // The value for this resource has never been set, // meaning we're good! entry->setItem(source, String16(nestedResourcePath)); break; } // We failed (name already exists), so try with a different name // (increment the suffix). } if (bundle->getVerbose()) { source.printf("generating nested resource %s:%s/%s", mAssets->getPackage().string(), target->getResourceType().string(), nestedResourceName.string()); } // Build the attribute reference and assign it to the parent. String16 nestedResourceRef = String16(String8::format("@%s:%s/%s", mAssets->getPackage().string(), target->getResourceType().string(), nestedResourceName.string())); String16 attrNs = buildNamespace(attrPackage); if (parent->getAttribute(attrNs, attrName) != NULL) { SourcePos(parent->getFilename(), parent->getStartLineNumber()) .error("parent of nested resource already defines attribute '%s:%s'", String8(attrPackage).string(), String8(attrName).string()); return UNKNOWN_ERROR; } // Add the reference to the inline resource. parent->addAttribute(attrNs, attrName, nestedResourceRef); // Remove the <aapt:attr> child element from here. children.removeAt(i); i--; // Append all namespace declarations that we've seen on this branch in the XML tree // to this resource. // We do this because the order of namespace declarations and prefix usage is determined // by the developer and we do not want to override any decisions. Be conservative. for (size_t nsIndex = namespaces->size(); nsIndex > 0; nsIndex--) { const sp<XMLNode>& ns = namespaces->itemAt(nsIndex - 1); sp<XMLNode> newNs = XMLNode::newNamespace(ns->getFilename(), ns->getNamespacePrefix(), ns->getNamespaceUri()); newNs->addChild(nestedRoot); nestedRoot = newNs; } // Schedule compilation of the nested resource. CompileResourceWorkItem workItem; workItem.resPath = nestedResourcePath; workItem.resourceName = String16(nestedResourceName); workItem.xmlRoot = nestedRoot; workItem.file = new AaptFile(target->getSourceFile(), target->getGroupEntry(), target->getResourceType()); mWorkQueue.push(workItem); } return NO_ERROR; }
tools/aapt/ResourceTable.h +0 −12 Original line number Diff line number Diff line Loading @@ -83,7 +83,6 @@ struct CompileResourceWorkItem { String16 resourceName; String8 resPath; sp<AaptFile> file; sp<XMLNode> xmlRoot; }; class ResourceTable : public ResTable::Accessor Loading Loading @@ -207,12 +206,6 @@ public: const sp<AaptFile>& file, const sp<XMLNode>& root); status_t processBundleFormat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& file, const sp<XMLNode>& parent); sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter, const bool isBase); Loading Loading @@ -593,11 +586,6 @@ private: Res_value* outValue); int getPublicAttributeSdkLevel(uint32_t attrId) const; status_t processBundleFormatImpl(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& file, const sp<XMLNode>& parent, Vector<sp<XMLNode> >* namespaces); String16 mAssetsPackage; PackageType mPackageType; Loading
tools/aapt/XMLNode.cpp +0 −18 Original line number Diff line number Diff line Loading @@ -693,12 +693,6 @@ const Vector<sp<XMLNode> >& XMLNode::getChildren() const return mChildren; } Vector<sp<XMLNode> >& XMLNode::getChildren() { return mChildren; } const String8& XMLNode::getFilename() const { return mFilename; Loading @@ -723,18 +717,6 @@ const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns, return NULL; } bool XMLNode::removeAttribute(const String16& ns, const String16& name) { for (size_t i = 0; i < mAttributes.size(); i++) { const attribute_entry& ae(mAttributes.itemAt(i)); if (ae.ns == ns && ae.name == name) { removeAttribute(i); return true; } } return false; } XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns, const String16& name) { Loading
tools/aapt/XMLNode.h +1 −3 Original line number Diff line number Diff line Loading @@ -70,7 +70,6 @@ public: const String16& getElementNamespace() const; const String16& getElementName() const; const Vector<sp<XMLNode> >& getChildren() const; Vector<sp<XMLNode> >& getChildren(); const String8& getFilename() const; Loading Loading @@ -98,7 +97,6 @@ public: const Vector<attribute_entry>& getAttributes() const; const attribute_entry* getAttribute(const String16& ns, const String16& name) const; bool removeAttribute(const String16& ns, const String16& name); attribute_entry* editAttribute(const String16& ns, const String16& name); Loading