diff options
Diffstat (limited to 'tools/aapt2/BinaryResourceParser.cpp')
| -rw-r--r-- | tools/aapt2/BinaryResourceParser.cpp | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp index 326a2ac..d16f63b 100644 --- a/tools/aapt2/BinaryResourceParser.cpp +++ b/tools/aapt2/BinaryResourceParser.cpp @@ -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) : @@ -401,6 +396,12 @@ bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) { } break; + case RES_TABLE_PUBLIC_TYPE: + if (!parsePublic(parser.getChunk())) { + return false; + } + break; + default: Logger::warn(mSource) << "unexpected chunk of type " @@ -434,6 +435,55 @@ bool BinaryResourceParser::parsePackage(const ResChunk_header* chunk) { return true; } +bool BinaryResourceParser::parsePublic(const ResChunk_header* chunk) { + const Public_header* header = convertTo<Public_header>(chunk); + + if (header->typeId == 0) { + Logger::error(mSource) + << "invalid type ID " << header->typeId << std::endl; + return false; + } + + const ResourceType* parsedType = parseResourceType(util::getString(mTypePool, + header->typeId - 1)); + if (!parsedType) { + Logger::error(mSource) + << "invalid type " << util::getString(mTypePool, header->typeId - 1) << std::endl; + return false; + } + + const uintptr_t chunkEnd = reinterpret_cast<uintptr_t>(chunk) + chunk->size; + const Public_entry* entry = reinterpret_cast<const Public_entry*>( + getChunkData(header->header)); + for (uint32_t i = 0; i < header->count; i++) { + if (reinterpret_cast<uintptr_t>(entry) + sizeof(*entry) > chunkEnd) { + Logger::error(mSource) + << "Public_entry extends beyond chunk." + << std::endl; + return false; + } + + const ResourceId resId = { mTable->getPackageId(), header->typeId, entry->entryId }; + const ResourceName name = { + mTable->getPackage(), + *parsedType, + util::getString(mKeyPool, entry->key.index).toString() }; + + SourceLine source; + if (mSourcePool.getError() == NO_ERROR) { + source.path = util::utf16ToUtf8(util::getString(mSourcePool, entry->source.index)); + source.line = entry->sourceLine; + } + + if (!mTable->markPublic(name, resId, source)) { + return false; + } + + entry++; + } + return true; +} + bool BinaryResourceParser::parseTypeSpec(const ResChunk_header* chunk) { if (mTypePool.getError() != NO_ERROR) { Logger::error(mSource) @@ -641,10 +691,6 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na return util::make_unique<BinaryPrimitive>(nullType); } - if (value->dataType == ExtendedTypes::TYPE_SENTINEL) { - return util::make_unique<Sentinel>(); - } - if (value->dataType == ExtendedTypes::TYPE_RAW_STRING) { return util::make_unique<RawString>( mTable->getValueStringPool().makeRef(util::getString(mValuePool, value->data), |
