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

Commit 01c1de58 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "AAPT2: Add library support"

parents 68e03ab9 769de98f
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ main := Main.cpp
sources := \
	BigBuffer.cpp \
	BinaryResourceParser.cpp \
	BinaryXmlPullParser.cpp \
	BindingXmlPullParser.cpp \
	ConfigDescription.cpp \
	Files.cpp \
@@ -51,7 +52,9 @@ sources := \
	ScopedXmlPullParser.cpp \
	SourceXmlPullParser.cpp \
	XliffXmlPullParser.cpp \
	XmlFlattener.cpp
	XmlFlattener.cpp \
	ZipEntry.cpp \
	ZipFile.cpp

testSources := \
	BigBuffer_test.cpp \
@@ -63,6 +66,7 @@ testSources := \
	Locale_test.cpp \
	ManifestParser_test.cpp \
	Maybe_test.cpp \
	NameMangler_test.cpp \
	ResourceParser_test.cpp \
	Resource_test.cpp \
	ResourceTable_test.cpp \
+40 −27
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "BinaryResourceParser.h"
#include "Logger.h"
#include "ResChunkPullParser.h"
#include "Resolver.h"
#include "ResourceParser.h"
#include "ResourceTable.h"
#include "ResourceTypeExtensions.h"
@@ -33,28 +34,14 @@ namespace aapt {

using namespace android;

template <typename T>
inline static const T* convertTo(const ResChunk_header* chunk) {
    if (chunk->headerSize < sizeof(T)) {
        return nullptr;
    }
    return reinterpret_cast<const T*>(chunk);
}

inline static const uint8_t* getChunkData(const ResChunk_header& chunk) {
    return reinterpret_cast<const uint8_t*>(&chunk) + chunk.headerSize;
}

inline static size_t getChunkDataLen(const ResChunk_header& chunk) {
    return chunk.size - chunk.headerSize;
}

/*
 * Visitor that converts a reference's resource ID to a resource name,
 * given a mapping from resource ID to resource name.
 */
struct ReferenceIdToNameVisitor : ValueVisitor {
    ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceName>& cache) : mCache(cache) {
    ReferenceIdToNameVisitor(const std::shared_ptr<Resolver>& resolver,
                             std::map<ResourceId, ResourceName>* cache) :
            mResolver(resolver), mCache(cache) {
    }

    void visit(Reference& reference, ValueVisitorArgs&) override {
@@ -104,24 +91,39 @@ private:
            return;
        }

        auto cacheIter = mCache.find(reference.id);
        if (cacheIter == std::end(mCache)) {
            Logger::note() << "failed to find " << reference.id << std::endl;
        } else {
        auto cacheIter = mCache->find(reference.id);
        if (cacheIter != mCache->end()) {
            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;

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

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


BinaryResourceParser::BinaryResourceParser(std::shared_ptr<ResourceTable> table,
BinaryResourceParser::BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                                           const std::shared_ptr<Resolver>& resolver,
                                           const Source& source,
                                           const void* data,
                                           size_t len) :
        mTable(table), mSource(source), mData(data), mDataLen(len) {
        mTable(table), mResolver(resolver), mSource(source), mData(data), mDataLen(len) {
}

bool BinaryResourceParser::parse() {
@@ -421,7 +423,7 @@ bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) {
    // Now go through the table and change resource ID references to
    // symbolic references.

    ReferenceIdToNameVisitor visitor(mIdIndex);
    ReferenceIdToNameVisitor visitor(mResolver, &mIdIndex);
    for (auto& type : *mTable) {
        for (auto& entry : type->entries) {
            for (auto& configValue : entry->values) {
@@ -676,7 +678,8 @@ std::unique_ptr<Value> BinaryResourceParser::parseMapEntry(const ResourceNameRef
std::unique_ptr<Style> BinaryResourceParser::parseStyle(const ResourceNameRef& name,
                                                        const ConfigDescription& config,
                                                        const ResTable_map_entry* map) {
    std::unique_ptr<Style> style = util::make_unique<Style>();
    const bool isWeak = (map->flags & ResTable_entry::FLAG_WEAK) != 0;
    std::unique_ptr<Style> style = util::make_unique<Style>(isWeak);
    if (map->parent.ident == 0) {
        // The parent is either not set or it is an unresolved symbol.
        // Check to see if it is a symbol.
@@ -759,8 +762,18 @@ std::unique_ptr<Styleable> BinaryResourceParser::parseStyleable(const ResourceNa
                                                                const ResTable_map_entry* map) {
    std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
    for (const ResTable_map& mapEntry : map) {
        if (mapEntry.name.ident == 0) {
            // The map entry's key (attribute) is not set. This must be
            // a symbol reference, so resolve it.
            ResourceNameRef symbol;
            bool result = getSymbol(&mapEntry.name.ident, &symbol);
            assert(result);
            styleable->entries.emplace_back(symbol);
        } else {
            // The map entry's key (attribute) is a regular reference.
            styleable->entries.emplace_back(mapEntry.name.ident);
        }
    }
    return styleable;
}

+6 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef AAPT_BINARY_RESOURCE_PARSER_H
#define AAPT_BINARY_RESOURCE_PARSER_H

#include "Resolver.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
#include "Source.h"
@@ -41,7 +42,9 @@ public:
     * Creates a parser, which will read `len` bytes from `data`, and
     * add any resources parsed to `table`. `source` is for logging purposes.
     */
    BinaryResourceParser(std::shared_ptr<ResourceTable> table, const Source& source,
    BinaryResourceParser(const std::shared_ptr<ResourceTable>& table,
                         const std::shared_ptr<Resolver>& resolver,
                         const Source& source,
                         const void* data, size_t len);

    BinaryResourceParser(const BinaryResourceParser&) = delete; // No copy.
@@ -89,6 +92,8 @@ private:

    std::shared_ptr<ResourceTable> mTable;

    std::shared_ptr<Resolver> mResolver;

    const Source mSource;

    const void* mData;
+204 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BinaryXmlPullParser.h"

#include <androidfw/ResourceTypes.h>
#include <memory>
#include <string>
#include <vector>

namespace aapt {

static XmlPullParser::Event codeToEvent(android::ResXMLParser::event_code_t code) {
    switch (code) {
        case android::ResXMLParser::START_DOCUMENT:
            return XmlPullParser::Event::kStartDocument;
        case android::ResXMLParser::END_DOCUMENT:
            return XmlPullParser::Event::kEndDocument;
        case android::ResXMLParser::START_NAMESPACE:
            return XmlPullParser::Event::kStartNamespace;
        case android::ResXMLParser::END_NAMESPACE:
            return XmlPullParser::Event::kEndNamespace;
        case android::ResXMLParser::START_TAG:
            return XmlPullParser::Event::kStartElement;
        case android::ResXMLParser::END_TAG:
            return XmlPullParser::Event::kEndElement;
        case android::ResXMLParser::TEXT:
            return XmlPullParser::Event::kText;
        default:
            break;
    }
    return XmlPullParser::Event::kBadDocument;
}

BinaryXmlPullParser::BinaryXmlPullParser(const std::shared_ptr<android::ResXMLTree>& parser)
    : mParser(parser), mEvent(Event::kStartDocument), mHasComment(false), sEmpty(), sEmpty8(),
      mDepth(0) {
}

XmlPullParser::Event BinaryXmlPullParser::next() {
    mStr1.clear();
    mStr2.clear();
    mAttributes.clear();

    android::ResXMLParser::event_code_t code;
    if (mHasComment) {
        mHasComment = false;
        code = mParser->getEventType();
    } else {
        code = mParser->next();
        if (code != android::ResXMLParser::BAD_DOCUMENT) {
            size_t len;
            const char16_t* comment = mParser->getComment(&len);
            if (comment) {
                mHasComment = true;
                mStr1.assign(comment, len);
                return XmlPullParser::Event::kComment;
            }
        }
    }

    size_t len;
    const char16_t* data;
    mEvent = codeToEvent(code);
    switch (mEvent) {
        case Event::kStartNamespace:
        case Event::kEndNamespace:
            data = mParser->getNamespacePrefix(&len);
            mStr1.assign(data, len);
            data = mParser->getNamespaceUri(&len);
            mStr2.assign(data, len);
            break;

        case Event::kStartElement:
            copyAttributes();
            // fallthrough

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

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

        default:
            break;
    }
    return mEvent;
}

XmlPullParser::Event BinaryXmlPullParser::getEvent() const {
    if (mHasComment) {
        return XmlPullParser::Event::kComment;
    }
    return mEvent;
}

const std::string& BinaryXmlPullParser::getLastError() const {
    return sEmpty8;
}

const std::u16string& BinaryXmlPullParser::getComment() const {
    if (mHasComment) {
        return mStr1;
    }
    return sEmpty;
}

size_t BinaryXmlPullParser::getLineNumber() const {
    return mParser->getLineNumber();
}

size_t BinaryXmlPullParser::getDepth() const {
    return mDepth;
}

const std::u16string& BinaryXmlPullParser::getText() const {
    if (!mHasComment && mEvent == XmlPullParser::Event::kText) {
        return mStr1;
    }
    return sEmpty;
}

const std::u16string& BinaryXmlPullParser::getNamespacePrefix() const {
    if (!mHasComment && (mEvent == XmlPullParser::Event::kStartNamespace ||
            mEvent == XmlPullParser::Event::kEndNamespace)) {
        return mStr1;
    }
    return sEmpty;
}

const std::u16string& BinaryXmlPullParser::getNamespaceUri() const {
    if (!mHasComment && (mEvent == XmlPullParser::Event::kStartNamespace ||
            mEvent == XmlPullParser::Event::kEndNamespace)) {
        return mStr2;
    }
    return sEmpty;
}

const std::u16string& BinaryXmlPullParser::getElementNamespace() const {
    if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
            mEvent == XmlPullParser::Event::kEndElement)) {
        return mStr1;
    }
    return sEmpty;
}

const std::u16string& BinaryXmlPullParser::getElementName() const {
    if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
            mEvent == XmlPullParser::Event::kEndElement)) {
        return mStr2;
    }
    return sEmpty;
}

size_t BinaryXmlPullParser::getAttributeCount() const {
    return mAttributes.size();
}

XmlPullParser::const_iterator BinaryXmlPullParser::beginAttributes() const {
    return mAttributes.begin();
}

XmlPullParser::const_iterator BinaryXmlPullParser::endAttributes() const {
    return mAttributes.end();
}

void BinaryXmlPullParser::copyAttributes() {
    const size_t attrCount = mParser->getAttributeCount();
    if (attrCount > 0) {
        mAttributes.reserve(attrCount);
        for (size_t i = 0; i < attrCount; i++) {
            XmlPullParser::Attribute attr;
            size_t len;
            const char16_t* str = mParser->getAttributeNamespace(i, &len);
            attr.namespaceUri.assign(str, len);
            str = mParser->getAttributeName(i, &len);
            attr.name.assign(str, len);
            str = mParser->getAttributeStringValue(i, &len);
            attr.value.assign(str, len);
            mAttributes.push_back(std::move(attr));
        }
    }
}

} // namespace aapt
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef AAPT_BINARY_XML_PULL_PARSER_H
#define AAPT_BINARY_XML_PULL_PARSER_H

#include "XmlPullParser.h"

#include <androidfw/ResourceTypes.h>
#include <memory>
#include <string>
#include <vector>

namespace aapt {

/**
 * Wraps a ResTable into the canonical XmlPullParser interface.
 */
class BinaryXmlPullParser : public XmlPullParser {
public:
    BinaryXmlPullParser(const std::shared_ptr<android::ResXMLTree>& parser);
    BinaryXmlPullParser(const BinaryXmlPullParser& rhs) = delete;

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

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

    const std::u16string& getText() const;

    const std::u16string& getNamespacePrefix() const;
    const std::u16string& getNamespaceUri() const;

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

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

private:
    void copyAttributes();

    std::shared_ptr<android::ResXMLTree> mParser;
    std::u16string mStr1;
    std::u16string mStr2;
    std::vector<Attribute> mAttributes;
    Event mEvent;
    bool mHasComment;
    const std::u16string sEmpty;
    const std::string sEmpty8;
    size_t mDepth;
};

} // namespace aapt

#endif // AAPT_BINARY_XML_PULL_PARSER_H
Loading