Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b9847ca authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Revert "Implement AAPT Bundle format"

This reverts commit 9d0f7d44.

Caused a build breakage when parsing some attributes.

Change-Id: I89ca958b2f2e820d353648df8aadd90bbe8d8339
parent 9d0f7d44
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -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,
+3 −230
Original line number Diff line number Diff line
@@ -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) {
@@ -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.
@@ -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);
    }

@@ -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;
}
+0 −12
Original line number Diff line number Diff line
@@ -83,7 +83,6 @@ struct CompileResourceWorkItem {
    String16 resourceName;
    String8 resPath;
    sp<AaptFile> file;
    sp<XMLNode> xmlRoot;
};

class ResourceTable : public ResTable::Accessor
@@ -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);

@@ -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;
+0 −18
Original line number Diff line number Diff line
@@ -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;
@@ -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)
{
+1 −3
Original line number Diff line number Diff line
@@ -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;
    
@@ -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);