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

Commit 24aad163 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Add namespace handling in attribute values

Previously, you could only reference namespace prefixes in attribute names:

<View xmlns:appcompat="http://schemas.android.com/apk/res/android.support.v7.appcompat"
      appcompat:name="hey"
      ...

Now you can also reference them in resource names within an attribute value:

      ...
      android:text="@appcompat:string/confirm"
      ...

Which will be treated as "@android.support.v7.appcompat:string/confirm".

Change-Id: Ib076e867a990c80cf877a704eb77cd1ef0b23b52
parent ab258139
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,10 +40,10 @@ sources := \
	ManifestValidator.cpp \
	Png.cpp \
	ResChunkPullParser.cpp \
	Resolver.cpp \
	Resource.cpp \
	ResourceParser.cpp \
	ResourceTable.cpp \
	ResourceTableResolver.cpp \
	ResourceValues.cpp \
	SdkConstants.cpp \
	StringPool.cpp \
+8 −13
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ using namespace android;
 * given a mapping from resource ID to resource name.
 */
struct ReferenceIdToNameVisitor : ValueVisitor {
    ReferenceIdToNameVisitor(const std::shared_ptr<Resolver>& resolver,
    ReferenceIdToNameVisitor(const std::shared_ptr<IResolver>& resolver,
                             std::map<ResourceId, ResourceName>* cache) :
            mResolver(resolver), mCache(cache) {
    }
@@ -96,30 +96,25 @@ private:
            reference.name = cacheIter->second;
            reference.id = 0;
        } else {
            const android::ResTable& table = mResolver->getResTable();
            android::ResTable::resource_name resourceName;
            if (table.getResourceName(reference.id.id, false, &resourceName)) {
                const ResourceType* type = parseResourceType(StringPiece16(resourceName.type,
                                                                           resourceName.typeLen));
                assert(type);
                reference.name.package.assign(resourceName.package, resourceName.packageLen);
                reference.name.type = *type;
                reference.name.entry.assign(resourceName.name, resourceName.nameLen);
                reference.id = 0;
            Maybe<ResourceName> result = mResolver->findName(reference.id);
            if (result) {
                reference.name = result.value();

                // Add to cache.
                mCache->insert({reference.id, reference.name});

                reference.id = 0;
            }
        }
    }

    std::shared_ptr<Resolver> mResolver;
    std::shared_ptr<IResolver> mResolver;
    std::map<ResourceId, ResourceName>* mCache;
};


BinaryResourceParser::BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                                           const std::shared_ptr<Resolver>& resolver,
                                           const std::shared_ptr<IResolver>& resolver,
                                           const Source& source,
                                           const void* data,
                                           size_t len) :
+2 −2
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ public:
     * add any resources parsed to `table`. `source` is for logging purposes.
     */
    BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                         const std::shared_ptr<Resolver>& resolver,
                         const std::shared_ptr<IResolver>& resolver,
                         const Source& source,
                         const void* data, size_t len);

@@ -92,7 +92,7 @@ private:

    std::shared_ptr<ResourceTable> mTable;

    std::shared_ptr<Resolver> mResolver;
    std::shared_ptr<IResolver> mResolver;

    const Source mSource;

+64 −9
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */

#include "BinaryXmlPullParser.h"
#include "Maybe.h"
#include "Util.h"

#include <androidfw/ResourceTypes.h>
#include <memory>
@@ -77,12 +79,31 @@ XmlPullParser::Event BinaryXmlPullParser::next() {
    mEvent = codeToEvent(code);
    switch (mEvent) {
        case Event::kStartNamespace:
        case Event::kEndNamespace:
        case Event::kEndNamespace: {
            data = mParser->getNamespacePrefix(&len);
            if (data) {
                mStr1.assign(data, len);
            } else {
                mStr1.clear();
            }
            data = mParser->getNamespaceUri(&len);
            if (data) {
                mStr2.assign(data, len);
            } else {
                mStr2.clear();
            }

            Maybe<std::u16string> result = util::extractPackageFromNamespace(mStr2);
            if (result) {
                if (mEvent == Event::kStartNamespace) {
                    mPackageAliases.emplace_back(mStr1, result.value());
                } else {
                    assert(mPackageAliases.back().second == result.value());
                    mPackageAliases.pop_back();
                }
            }
            break;
        }

        case Event::kStartElement:
            copyAttributes();
@@ -90,14 +111,26 @@ XmlPullParser::Event BinaryXmlPullParser::next() {

        case Event::kEndElement:
            data = mParser->getElementNamespace(&len);
            if (data) {
                mStr1.assign(data, len);
            } else {
                mStr1.clear();
            }
            data = mParser->getElementName(&len);
            if (data) {
                mStr2.assign(data, len);
            } else {
                mStr2.clear();
            }
            break;

        case Event::kText:
            data = mParser->getText(&len);
            if (data) {
                mStr1.assign(data, len);
            } else {
                mStr1.clear();
            }
            break;

        default:
@@ -155,6 +188,22 @@ const std::u16string& BinaryXmlPullParser::getNamespaceUri() const {
    return sEmpty;
}

bool BinaryXmlPullParser::applyPackageAlias(std::u16string* package,
                                            const std::u16string& defaultPackage) const {
    const auto endIter = mPackageAliases.rend();
    for (auto iter = mPackageAliases.rbegin(); iter != endIter; ++iter) {
        if (iter->first == *package) {
            if (iter->second.empty()) {
                *package = defaultPackage;
            } else {
                *package = iter->second;
            }
            return true;
        }
    }
    return false;
}

const std::u16string& BinaryXmlPullParser::getElementNamespace() const {
    if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
            mEvent == XmlPullParser::Event::kEndElement)) {
@@ -191,11 +240,17 @@ void BinaryXmlPullParser::copyAttributes() {
            XmlPullParser::Attribute attr;
            size_t len;
            const char16_t* str = mParser->getAttributeNamespace(i, &len);
            if (str) {
                attr.namespaceUri.assign(str, len);
            }
            str = mParser->getAttributeName(i, &len);
            if (str) {
                attr.name.assign(str, len);
            }
            str = mParser->getAttributeStringValue(i, &len);
            if (str) {
                attr.value.assign(str, len);
            }
            mAttributes.push_back(std::move(attr));
        }
    }
+17 −14
Original line number Diff line number Diff line
@@ -34,25 +34,27 @@ public:
    BinaryXmlPullParser(const std::shared_ptr<android::ResXMLTree>& parser);
    BinaryXmlPullParser(const BinaryXmlPullParser& rhs) = delete;

    Event getEvent() const;
    const std::string& getLastError() const;
    Event next();
    Event getEvent() const override;
    const std::string& getLastError() const override;
    Event next() override;

    const std::u16string& getComment() const;
    size_t getLineNumber() const;
    size_t getDepth() const;
    const std::u16string& getComment() const override;
    size_t getLineNumber() const override;
    size_t getDepth() const override;

    const std::u16string& getText() const;
    const std::u16string& getText() const override;

    const std::u16string& getNamespacePrefix() const;
    const std::u16string& getNamespaceUri() const;
    const std::u16string& getNamespacePrefix() const override;
    const std::u16string& getNamespaceUri() const override;
    bool applyPackageAlias(std::u16string* package, const std::u16string& defaultpackage)
            const override;

    const std::u16string& getElementNamespace() const;
    const std::u16string& getElementName() const;
    const std::u16string& getElementNamespace() const override;
    const std::u16string& getElementName() const override;

    const_iterator beginAttributes() const;
    const_iterator endAttributes() const;
    size_t getAttributeCount() const;
    const_iterator beginAttributes() const override;
    const_iterator endAttributes() const override;
    size_t getAttributeCount() const override;

private:
    void copyAttributes();
@@ -66,6 +68,7 @@ private:
    const std::u16string sEmpty;
    const std::string sEmpty8;
    size_t mDepth;
    std::vector<std::pair<std::u16string, std::u16string>> mPackageAliases;
};

} // namespace aapt
Loading