16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License. 66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at 76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and 146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License. 156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 17b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski#include "unflatten/BinaryResourceParser.h" 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <algorithm> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <map> 21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <string> 22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h" 24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/macros.h" 259431c476f35431f45a13c257b305e9999821190dAdam Lesinski#include "android-base/stringprintf.h" 26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "androidfw/ResourceTypes.h" 27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "androidfw/TypeWrappers.h" 28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceTable.h" 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceUtils.h" 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "ResourceValues.h" 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include "Source.h" 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ValueVisitor.h" 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "unflatten/ResChunkPullParser.h" 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiusing namespace android; 406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 419431c476f35431f45a13c257b305e9999821190dAdam Lesinskiusing android::base::StringPrintf; 429431c476f35431f45a13c257b305e9999821190dAdam Lesinski 4359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskinamespace { 4459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/* 466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Visitor that converts a reference's resource ID to a resource name, 476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * given a mapping from resource ID to resource name. 486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass ReferenceIdToNameVisitor : public ValueVisitor { 50b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski public: 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski using ValueVisitor::Visit; 526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 53b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski explicit ReferenceIdToNameVisitor( 54b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const std::map<ResourceId, ResourceName>* mapping) 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : mapping_(mapping) { 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(mapping_ != nullptr); 57b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski void Visit(Reference* reference) override { 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!reference->id || !reference->id.value().is_valid()) { 61b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return; 62b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 64b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski ResourceId id = reference->id.value(); 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto cache_iter = mapping_->find(id); 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (cache_iter != mapping_->end()) { 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski reference->name = cache_iter->second; 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 69b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private: 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DISALLOW_COPY_AND_ASSIGN(ReferenceIdToNameVisitor); 73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::map<ResourceId, ResourceName>* mapping_; 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 77b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski} // namespace 7859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 79d0f492db038c6210c1138865d816bfb134376538Adam LesinskiBinaryResourceParser::BinaryResourceParser(IAaptContext* context, ResourceTable* table, 80d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const Source& source, const void* data, size_t len, 81d0f492db038c6210c1138865d816bfb134376538Adam Lesinski io::IFileCollection* files) 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski : context_(context), 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_(table), 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski source_(source), 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski data_(data), 86d0f492db038c6210c1138865d816bfb134376538Adam Lesinski data_len_(len), 87d0f492db038c6210c1138865d816bfb134376538Adam Lesinski files_(files) { 88d0f492db038c6210c1138865d816bfb134376538Adam Lesinski} 896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool BinaryResourceParser::Parse() { 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResChunkPullParser parser(data_, data_len_); 926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 939431c476f35431f45a13c257b305e9999821190dAdam Lesinski if (!ResChunkPullParser::IsGoodEvent(parser.Next())) { 949431c476f35431f45a13c257b305e9999821190dAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 959431c476f35431f45a13c257b305e9999821190dAdam Lesinski << "corrupt resources.arsc: " << parser.error()); 969431c476f35431f45a13c257b305e9999821190dAdam Lesinski return false; 979431c476f35431f45a13c257b305e9999821190dAdam Lesinski } 986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 999431c476f35431f45a13c257b305e9999821190dAdam Lesinski if (parser.chunk()->type != android::RES_TABLE_TYPE) { 1009431c476f35431f45a13c257b305e9999821190dAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 1019431c476f35431f45a13c257b305e9999821190dAdam Lesinski << StringPrintf("unknown chunk of type 0x%02x", 1029431c476f35431f45a13c257b305e9999821190dAdam Lesinski (int)parser.chunk()->type)); 1039431c476f35431f45a13c257b305e9999821190dAdam Lesinski return false; 104b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 105b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 1069431c476f35431f45a13c257b305e9999821190dAdam Lesinski if (!ParseTable(parser.chunk())) { 107b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 108b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 1099431c476f35431f45a13c257b305e9999821190dAdam Lesinski 1109431c476f35431f45a13c257b305e9999821190dAdam Lesinski if (parser.Next() != ResChunkPullParser::Event::kEndDocument) { 1119431c476f35431f45a13c257b305e9999821190dAdam Lesinski if (parser.event() == ResChunkPullParser::Event::kBadDocument) { 1129431c476f35431f45a13c257b305e9999821190dAdam Lesinski context_->GetDiagnostics()->Warn( 1139431c476f35431f45a13c257b305e9999821190dAdam Lesinski DiagMessage(source_) << "invalid chunk trailing RES_TABLE_TYPE: " << parser.error()); 1149431c476f35431f45a13c257b305e9999821190dAdam Lesinski } else { 1159431c476f35431f45a13c257b305e9999821190dAdam Lesinski context_->GetDiagnostics()->Warn( 1169431c476f35431f45a13c257b305e9999821190dAdam Lesinski DiagMessage(source_) << StringPrintf( 1179431c476f35431f45a13c257b305e9999821190dAdam Lesinski "unexpected chunk of type 0x%02x trailing RES_TABLE_TYPE", 1189431c476f35431f45a13c257b305e9999821190dAdam Lesinski (int)parser.chunk()->type)); 1199431c476f35431f45a13c257b305e9999821190dAdam Lesinski } 1209431c476f35431f45a13c257b305e9999821190dAdam Lesinski } 1219431c476f35431f45a13c257b305e9999821190dAdam Lesinski return true; 1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/** 125b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski * Parses the resource table, which contains all the packages, types, and 126b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski * entries. 1271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool BinaryResourceParser::ParseTable(const ResChunk_header* chunk) { 129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResTable_header* table_header = ConvertTo<ResTable_header>(chunk); 130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!table_header) { 131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 132b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "corrupt ResTable_header chunk"); 133b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 134b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 135b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResChunkPullParser parser(GetChunkData(&table_header->header), 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GetChunkDataLen(&table_header->header)); 138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (ResChunkPullParser::IsGoodEvent(parser.Next())) { 139ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (util::DeviceToHost16(parser.chunk()->type)) { 140b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case android::RES_STRING_POOL_TYPE: 141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (value_pool_.getError() == NO_INIT) { 142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski status_t err = value_pool_.setTo( 143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski parser.chunk(), util::DeviceToHost32(parser.chunk()->size)); 144b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (err != NO_ERROR) { 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "corrupt string pool in ResTable: " 147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << value_pool_.getError()); 148b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 149b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 1506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 151b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // Reserve some space for the strings we are going to add. 152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski table_->string_pool.HintWillAdd(value_pool_.size(), 153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski value_pool_.styleCount()); 154b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } else { 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Warn( 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "unexpected string pool in ResTable"); 1576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 158b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 1596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 160b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case android::RES_TABLE_PACKAGE_TYPE: 161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!ParsePackage(parser.chunk())) { 162b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 163b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 164b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 165b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 166b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski default: 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Warn( 168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) 169b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "unexpected chunk type " 170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << (int)util::DeviceToHost16(parser.chunk()->type)); 171b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 172b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 173b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 174b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.event() == ResChunkPullParser::Event::kBadDocument) { 176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "corrupt resource table: " << parser.error()); 178b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 179b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 180b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return true; 1816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool BinaryResourceParser::ParsePackage(const ResChunk_header* chunk) { 18433af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski constexpr size_t kMinPackageSize = 18533af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski sizeof(ResTable_package) - sizeof(ResTable_package::typeIdOffset); 18633af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski const ResTable_package* package_header = ConvertTo<ResTable_package, kMinPackageSize>(chunk); 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!package_header) { 18833af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) << "corrupt ResTable_package chunk"); 189b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 190b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 191b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t package_id = util::DeviceToHost32(package_header->id); 193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (package_id > std::numeric_limits<uint8_t>::max()) { 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "package ID is too big (" << package_id << ")"); 196b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 197b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 198b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 199b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // Extract the package name. 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len = strnlen16((const char16_t*)package_header->name, 201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski arraysize(package_header->name)); 202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::u16string package_name; 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_name.resize(len); 204b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski for (size_t i = 0; i < len; i++) { 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_name[i] = util::DeviceToHost16(package_header->name[i]); 206b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 207b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResourceTablePackage* package = table_->CreatePackage( 209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::Utf16ToUtf8(package_name), static_cast<uint8_t>(package_id)); 210b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (!package) { 211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "incompatible package '" << package_name 213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << "' with ID " << package_id); 214b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 215b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 216b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 217b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // There can be multiple packages in a table, so 218b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // clear the type and key pool in case they were set from a previous package. 219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski type_pool_.uninit(); 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski key_pool_.uninit(); 221b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResChunkPullParser parser(GetChunkData(&package_header->header), 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski GetChunkDataLen(&package_header->header)); 224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (ResChunkPullParser::IsGoodEvent(parser.Next())) { 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (util::DeviceToHost16(parser.chunk()->type)) { 226b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case android::RES_STRING_POOL_TYPE: 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (type_pool_.getError() == NO_INIT) { 228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski status_t err = type_pool_.setTo( 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski parser.chunk(), util::DeviceToHost32(parser.chunk()->size)); 230b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (err != NO_ERROR) { 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 232b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "corrupt type string pool in " 233b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "ResTable_package: " 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << type_pool_.getError()); 235b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 236b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (key_pool_.getError() == NO_INIT) { 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski status_t err = key_pool_.setTo( 239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski parser.chunk(), util::DeviceToHost32(parser.chunk()->size)); 240b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (err != NO_ERROR) { 241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 242b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "corrupt key string pool in " 243b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "ResTable_package: " 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << key_pool_.getError()); 245b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 246b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 247b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } else { 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Warn(DiagMessage(source_) 249b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "unexpected string pool"); 2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 251b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 253b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case android::RES_TABLE_TYPE_SPEC_TYPE: 254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!ParseTypeSpec(parser.chunk())) { 255b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 256b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 257b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 259b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case android::RES_TABLE_TYPE_TYPE: 260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!ParseType(package, parser.chunk())) { 261b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 262b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 263b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 264b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 265ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski case android::RES_TABLE_LIBRARY_TYPE: 266ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (!ParseLibrary(parser.chunk())) { 267ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski return false; 268ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 269ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski break; 270ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 271b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski default: 272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Warn( 273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) 274b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "unexpected chunk type " 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << (int)util::DeviceToHost16(parser.chunk()->type)); 276b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 277b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 278b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 279b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (parser.event() == ResChunkPullParser::Event::kBadDocument) { 281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "corrupt ResTable_package: " << parser.error()); 283b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 284b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 285b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 286b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // Now go through the table and change local resource ID references to 287b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // symbolic references. 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ReferenceIdToNameVisitor visitor(&id_index_); 289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski VisitAllValuesInTable(table_, &visitor); 290b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return true; 2916ff19664f9279023c96e5a65c3059e1ef4beac0fAdam Lesinski} 2926ff19664f9279023c96e5a65c3059e1ef4beac0fAdam Lesinski 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool BinaryResourceParser::ParseTypeSpec(const ResChunk_header* chunk) { 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (type_pool_.getError() != NO_ERROR) { 295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 296b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "missing type string pool"); 297b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 298b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 299b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResTable_typeSpec* type_spec = ConvertTo<ResTable_typeSpec>(chunk); 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!type_spec) { 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 303b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "corrupt ResTable_typeSpec chunk"); 304b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 305b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 306b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (type_spec->id == 0) { 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 309b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "ResTable_typeSpec has invalid id: " 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << type_spec->id); 311b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 312b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 313b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return true; 3146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 3156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool BinaryResourceParser::ParseType(const ResourceTablePackage* package, 3171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const ResChunk_header* chunk) { 318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (type_pool_.getError() != NO_ERROR) { 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 320b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "missing type string pool"); 321b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 322b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 323b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (key_pool_.getError() != NO_ERROR) { 325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 326b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "missing key string pool"); 327b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 328b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 329b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 330136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6Adam Lesinski // Specify a manual size, because ResTable_type contains ResTable_config, which changes 331136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6Adam Lesinski // a lot and has its own code to handle variable size. 332136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6Adam Lesinski const ResTable_type* type = ConvertTo<ResTable_type, kResTableTypeMinSize>(chunk); 333b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (!type) { 334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 335b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "corrupt ResTable_type chunk"); 336b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 337b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 338b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 339b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (type->id == 0) { 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error(DiagMessage(source_) 341b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "ResTable_type has invalid id: " 342b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << (int)type->id); 343b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 344b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 345b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 346b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski ConfigDescription config; 347b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski config.copyFromDtoH(type->config); 348b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string type_str = util::GetString(type_pool_, type->id - 1); 350b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceType* parsed_type = ParseResourceType(type_str); 352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!parsed_type) { 353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "invalid type name '" << type_str 355b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << "' for type with ID " << (int)type->id); 356b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 357b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 358b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 359b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski TypeVariant tv(type); 360b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski for (auto it = tv.beginEntries(); it != tv.endEntries(); ++it) { 361b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_entry* entry = *it; 362b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (!entry) { 363b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski continue; 364b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 365b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 366b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceName name( 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package->name, *parsed_type, 368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::GetString(key_pool_, util::DeviceToHost32(entry->key.index))); 369b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const ResourceId res_id(package->id.value(), type->id, 371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski static_cast<uint16_t>(it.index())); 372b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Value> resource_value; 374b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (entry->flags & ResTable_entry::FLAG_COMPLEX) { 375d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const ResTable_map_entry* mapEntry = static_cast<const ResTable_map_entry*>(entry); 376b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 377b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // TODO(adamlesinski): Check that the entry count is valid. 378ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski resource_value = ParseMapEntry(name, config, mapEntry); 379b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } else { 380b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const Res_value* value = 381d0f492db038c6210c1138865d816bfb134376538Adam Lesinski (const Res_value*)((const uint8_t*)entry + util::DeviceToHost32(entry->size)); 382d0f492db038c6210c1138865d816bfb134376538Adam Lesinski resource_value = ParseValue(name, config, *value); 383b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 384b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!resource_value) { 386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics()->Error( 387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DiagMessage(source_) << "failed to parse value for resource " << name 388ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << " (" << res_id << ") with configuration '" 389b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski << config << "'"); 390b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 391b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 392b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 3932599aa4dfd29627a5690460bdcd5568d1029d4dcPierre Lecesne if (!table_->AddResourceAllowMangled(name, res_id, config, {}, std::move(resource_value), 394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context_->GetDiagnostics())) { 395b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return false; 396b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 397b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 398b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) { 399b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski Symbol symbol; 400b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski symbol.state = SymbolState::kPublic; 401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski symbol.source = source_.WithLine(0); 402d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (!table_->SetSymbolStateAllowMangled(name, res_id, symbol, context_->GetDiagnostics())) { 4036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return false; 404b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 4056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 4066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 407b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // Add this resource name->id mapping to the index so 408b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // that we can resolve all ID references to name references. 409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto cache_iter = id_index_.find(res_id); 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (cache_iter == id_index_.end()) { 411ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski id_index_.insert({res_id, name}); 4126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski } 413b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 414b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return true; 4156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 417ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinskibool BinaryResourceParser::ParseLibrary(const ResChunk_header* chunk) { 418ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski DynamicRefTable dynamic_ref_table; 419ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski if (dynamic_ref_table.load(reinterpret_cast<const ResTable_lib_header*>(chunk)) != NO_ERROR) { 420ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski return false; 421ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 422ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 423ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski const KeyedVector<String16, uint8_t>& entries = dynamic_ref_table.entries(); 424ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski const size_t count = entries.size(); 425ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski for (size_t i = 0; i < count; i++) { 426ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski table_->included_packages_[entries.valueAt(i)] = 427ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::Utf16ToUtf8(StringPiece16(entries.keyAt(i).string())); 428ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski } 429ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski return true; 430ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski} 431ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski 432d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistd::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& name, 433d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const ConfigDescription& config, 434d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const android::Res_value& value) { 435d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<Item> item = ResourceUtils::ParseBinaryResValue(name.type, config, value_pool_, 436d0f492db038c6210c1138865d816bfb134376538Adam Lesinski value, &table_->string_pool); 437d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (files_ != nullptr && item != nullptr) { 438d0f492db038c6210c1138865d816bfb134376538Adam Lesinski FileReference* file_ref = ValueCast<FileReference>(item.get()); 439d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (file_ref != nullptr) { 440d0f492db038c6210c1138865d816bfb134376538Adam Lesinski file_ref->file = files_->FindFile(*file_ref->path); 441d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (file_ref->file == nullptr) { 442742888f0fd9f00574049f52f6ede610888eea4edAdam Lesinski context_->GetDiagnostics()->Warn(DiagMessage() << "resource " << name << " for config '" 443d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << config << "' is a file reference to '" 444d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << *file_ref->path 445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "' but no such path exists"); 446b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 447b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski } 448b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 449d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return item; 4506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Value> BinaryResourceParser::ParseMapEntry( 453b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 454b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_map_entry* map) { 455b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski switch (name.type) { 456b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResourceType::kStyle: 457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ParseStyle(name, config, map); 458b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResourceType::kAttrPrivate: 459b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // fallthrough 460b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResourceType::kAttr: 461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ParseAttr(name, config, map); 462b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResourceType::kArray: 463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ParseArray(name, config, map); 464b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResourceType::kPlurals: 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ParsePlural(name, config, map); 46633af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski case ResourceType::kId: 46733af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski // Special case: An ID is not a bag, but some apps have defined the auto-generated 46833af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski // IDs that come from declaring an enum value in an attribute as an empty map... 46933af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski // We can ignore the value here. 47033af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski return util::make_unique<Id>(); 471b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski default: 47233af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski context_->GetDiagnostics()->Error(DiagMessage() << "illegal map type '" << ToString(name.type) 47333af6c730f9f7fc51f04516c7a22cac82cb9823eAdam Lesinski << "' (" << (int)name.type << ")"); 474b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 475b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 476b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return {}; 4776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 4786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Style> BinaryResourceParser::ParseStyle( 480b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 481b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_map_entry* map) { 482b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski std::unique_ptr<Style> style = util::make_unique<Style>(); 483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (util::DeviceToHost32(map->parent.ident) != 0) { 484b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // The parent is a regular reference to a resource. 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski style->parent = Reference(util::DeviceToHost32(map->parent.ident)); 486b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 487b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const ResTable_map& map_entry : map) { 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Res_INTERNALID(util::DeviceToHost32(map_entry.name.ident))) { 490b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski continue; 491b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 492b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Style::Entry style_entry; 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski style_entry.key = Reference(util::DeviceToHost32(map_entry.name.ident)); 495d0f492db038c6210c1138865d816bfb134376538Adam Lesinski style_entry.value = ParseValue(name, config, map_entry.value); 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!style_entry.value) { 497b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return {}; 498b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski style->entries.push_back(std::move(style_entry)); 500b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 501b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return style; 5026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Attribute> BinaryResourceParser::ParseAttr( 505b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 506b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_map_entry* map) { 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const bool is_weak = 508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (util::DeviceToHost16(map->flags) & ResTable_entry::FLAG_WEAK) != 0; 509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak); 510b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 511b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // First we must discover what type of attribute this is. Find the type mask. 512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto type_mask_iter = 513b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski std::find_if(begin(map), end(map), [](const ResTable_map& entry) -> bool { 514ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return util::DeviceToHost32(entry.name.ident) == 515b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski ResTable_map::ATTR_TYPE; 516b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski }); 517b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (type_mask_iter != end(map)) { 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr->type_mask = util::DeviceToHost32(type_mask_iter->value.data); 520b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 521b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 522ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const ResTable_map& map_entry : map) { 523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Res_INTERNALID(util::DeviceToHost32(map_entry.name.ident))) { 524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (util::DeviceToHost32(map_entry.name.ident)) { 525b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_MIN: 526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr->min_int = static_cast<int32_t>(map_entry.value.data); 527b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 528b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_MAX: 529ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr->max_int = static_cast<int32_t>(map_entry.value.data); 530b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 531b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 532b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski continue; 533b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 534b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 535ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr->type_mask & 536ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) { 537b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski Attribute::Symbol symbol; 538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski symbol.value = util::DeviceToHost32(map_entry.value.data); 539ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski symbol.symbol = Reference(util::DeviceToHost32(map_entry.name.ident)); 540b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski attr->symbols.push_back(std::move(symbol)); 541b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 542b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 543b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 544b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski // TODO(adamlesinski): Find i80n, attributes. 545b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return attr; 5466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Array> BinaryResourceParser::ParseArray( 549b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 550b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_map_entry* map) { 551b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski std::unique_ptr<Array> array = util::make_unique<Array>(); 552ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const ResTable_map& map_entry : map) { 553d0f492db038c6210c1138865d816bfb134376538Adam Lesinski array->items.push_back(ParseValue(name, config, map_entry.value)); 554b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 555b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return array; 5566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 558ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Plural> BinaryResourceParser::ParsePlural( 559b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResourceNameRef& name, const ConfigDescription& config, 560b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski const ResTable_map_entry* map) { 561b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski std::unique_ptr<Plural> plural = util::make_unique<Plural>(); 562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const ResTable_map& map_entry : map) { 563d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<Item> item = ParseValue(name, config, map_entry.value); 564b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski if (!item) { 565b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return {}; 566b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 567b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski 568ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (util::DeviceToHost32(map_entry.name.ident)) { 569b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_ZERO: 570b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::Zero] = std::move(item); 571b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 572b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_ONE: 573b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::One] = std::move(item); 574b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 575b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_TWO: 576b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::Two] = std::move(item); 577b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 578b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_FEW: 579b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::Few] = std::move(item); 580b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 581b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_MANY: 582b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::Many] = std::move(item); 583b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 584b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski case ResTable_map::ATTR_OTHER: 585b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski plural->values[Plural::Other] = std::move(item); 586b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski break; 587b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 588b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski } 589b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski return plural; 5906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 5916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 592b54ef10f55ab9f11fdc73b0436b708e518fb5029Adam Lesinski} // namespace aapt 593