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