Link.cpp revision d0f492db038c6210c1138865d816bfb134376538
11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License.
61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at
71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software
111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and
141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License.
151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
17ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <sys/stat.h>
18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <fstream>
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <queue>
21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <unordered_map>
22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector>
23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/errors.h"
25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/file.h"
26f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski#include "android-base/stringprintf.h"
27d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "google/protobuf/io/coded_stream.h"
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "AppInfo.h"
311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Debug.h"
321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Flags.h"
336a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski#include "Locale.h"
341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "NameMangler.h"
3559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "ResourceUtils.h"
36d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "cmd/Util.h"
371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "compile/IdAssigner.h"
386a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski#include "filter/ConfigFilter.h"
391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/Archive.h"
401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/TableFlattener.h"
411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/XmlFlattener.h"
4206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski#include "io/BigBufferInputStream.h"
43a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include "io/FileSystem.h"
44d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "io/Util.h"
45a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski#include "io/ZipArchive.h"
46ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/JavaClassGenerator.h"
47ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ManifestClassGenerator.h"
48ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ProguardRules.h"
491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/Linkers.h"
50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include "link/ManifestFixer.h"
51467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "link/ReferenceLinker.h"
521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "link/TableMerger.h"
53d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/ResourceDeduper.h"
54d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/VersionCollapser.h"
551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/IResourceTableConsumer.h"
561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/SymbolTable.h"
5759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h"
58355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "split/TableSplitter.h"
591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "unflatten/BinaryResourceParser.h"
601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Files.h"
61467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h"
621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
63d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece;
64f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinskiusing android::base::StringPrintf;
655eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
68ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski// The type of package to build.
69ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinskienum class PackageType {
70ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  kApp,
71ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  kSharedLib,
72ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  kStaticLib,
73ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski};
74ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct LinkOptions {
76ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  PackageType package_type = PackageType::kApp;
77ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output_path;
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string manifest_path;
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> include_paths;
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_files;
82b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  std::vector<std::string> assets_dirs;
83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool output_to_directory = false;
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool auto_add_overlay = false;
85cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Java/Proguard options.
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_java_class_path;
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> custom_java_package;
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::set<std::string> extra_java_packages;
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_proguard_rules_path;
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_main_dex_proguard_rules_path;
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool generate_non_final_ids = false;
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> javadoc_annotations;
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> private_symbols;
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Optimizations/features.
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
994d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_resource_deduping = false;
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Static lib options.
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_static_lib_packages = false;
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // AndroidManifest.xml massaging options.
109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ManifestFixerOptions manifest_fixer_options;
110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Products to use/filter on.
112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unordered_set<std::string> products;
113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
114c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  // Flattening options.
115c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  TableFlattenerOptions table_flattener_options;
116c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski
117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Split APK options.
118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  TableSplitterOptions table_splitter_options;
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<SplitConstraints> split_constraints;
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_paths;
121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
122cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Stable ID options.
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_map<ResourceName, ResourceId> stable_id_map;
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> resource_id_map_path;
1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
12764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass LinkContext : public IAaptContext {
128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
129d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  LinkContext() : name_mangler_({}), symbols_(&name_mangler_) {
130d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
132d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  IDiagnostics* GetDiagnostics() override {
133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &diagnostics_;
134d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
136d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  NameMangler* GetNameMangler() override {
137d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &name_mangler_;
138d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
140ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void SetNameManglerPolicy(const NameManglerPolicy& policy) {
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    name_mangler_ = NameMangler(policy);
142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const std::string& GetCompilationPackage() override {
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return compilation_package_;
146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void SetCompilationPackage(const StringPiece& package_name) {
149d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    compilation_package_ = package_name.to_string();
150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
15164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
152d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  uint8_t GetPackageId() override {
153d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return package_id_;
154d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
156d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetPackageId(uint8_t id) {
157d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    package_id_ = id;
158d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
15964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
160d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  SymbolTable* GetExternalSymbols() override {
161d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &symbols_;
162d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
163355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
164d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool IsVerbose() override {
165d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return verbose_;
166d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
16764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
168d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetVerbose(bool val) {
169d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    verbose_ = val;
170d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
17164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
172d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  int GetMinSdkVersion() override {
173d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return min_sdk_version_;
174d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
175fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
176d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetMinSdkVersion(int minSdk) {
177d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    min_sdk_version_ = minSdk;
178d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
179fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(LinkContext);
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  StdErrDiagnostics diagnostics_;
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  NameMangler name_mangler_;
185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string compilation_package_;
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint8_t package_id_ = 0x0;
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SymbolTable symbols_;
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool verbose_ = false;
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int min_sdk_version_ = 0;
1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path,
193d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                       Maybe<size_t> max_sdk_level, bool keep_raw_values, IArchiveWriter* writer,
194d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                       IAaptContext* context) {
195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  BigBuffer buffer(1024);
196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattenerOptions options = {};
197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.keep_raw_values = keep_raw_values;
198ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.max_sdk_level = max_sdk_level;
199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattener flattener(&buffer, options);
200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flattener.Consume(context, xml_res)) {
201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (context->IsVerbose()) {
205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    DiagMessage msg;
206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    msg << "writing " << path << " to archive";
207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (max_sdk_level) {
208d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      msg << " maxSdkLevel=" << max_sdk_level.value() << " keepRawValues=" << keep_raw_values;
209355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context->GetDiagnostics()->Note(msg);
211cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
21259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
21306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  io::BigBufferInputStream input_stream(&buffer);
214d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
215d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                      ArchiveEntry::kCompress, writer);
216355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
21759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
218d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data,
219d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      size_t len, IDiagnostics* diag) {
220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  pb::ResourceTable pb_table;
221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!pb_table.ParseFromArray(data, len)) {
222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(source) << "invalid compiled table");
223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
225cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
22606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::unique_ptr<ResourceTable> table = DeserializeTableFromPb(pb_table, source, diag);
227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!table) {
228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
229cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return table;
231355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
2321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
233355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/**
234355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Inflates an XML file from the source path.
235355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */
236d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::ifstream fin(path, std::ifstream::binary);
238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fin) {
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << strerror(errno));
240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return xml::Inflate(&fin, diag, Source(path));
243355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
2441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
245355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistruct ResourceFileFlattenerOptions {
246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
2484d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool keep_raw_values = false;
251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool update_proguard_spec = false;
253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
254355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
255355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
256355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass ResourceFileFlattener {
257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
258d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context,
259d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        proguard::KeepSet* keep_set)
260d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      : options_(options), context_(context), keep_set_(keep_set) {
261d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
2621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer);
264355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
266cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  struct FileOperation {
267cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ConfigDescription config;
2685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The entry this file came from.
270cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceEntry* entry;
2715eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
272cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The file to copy as-is.
273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file_to_copy;
2745eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
275cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The XML to process and flatten.
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> xml_to_flatten;
2775eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
278cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The destination to write this file to.
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string dst_path;
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool skip_version = false;
281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  };
282355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint32_t GetCompressionFlags(const StringPiece& str);
284355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                             std::queue<FileOperation>* out_file_op_queue);
287355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceFileFlattenerOptions options_;
289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  IAaptContext* context_;
290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  proguard::KeepSet* keep_set_;
291355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
292355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiuint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.do_not_compress_anything) {
295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
297355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& extension : options_.extensions_to_not_compress) {
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(str, extension)) {
300cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 0;
301355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
302cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
303cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return ArchiveEntry::kCompress;
304355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
305355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
3064d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const std::string& name) {
307d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
308d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeImageTransform" || name == "changeTransform" ||
309d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
310d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeScroll" || name == "transitionSet" || name == "transition" ||
311d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "transitionManager";
3124d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki}
3134d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki
314d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
315d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  std::queue<FileOperation>* out_file_op_queue) {
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* doc = file_op->xml_to_flatten.get();
317cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const Source& src = doc->file.source;
318355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (context_->IsVerbose()) {
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path);
321cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
322355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XmlReferenceLinker xml_linker;
324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!xml_linker.Consume(context_, doc)) {
325cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
327355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
328d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) {
329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
330cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
331cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.no_xml_namespaces) {
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    XmlNamespaceRemover namespace_remover;
334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!namespace_remover.Consume(context_, doc)) {
335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
336355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
337cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
338355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!options_.no_auto_version) {
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.no_version_vectors) {
341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Skip this if it is a vector or animated-vector.
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      xml::Element* el = xml::FindRootElement(doc);
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (el && el->namespace_uri.empty()) {
344cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (el->name == "vector" || el->name == "animated-vector") {
345cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // We are NOT going to version this file.
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op->skip_version = true;
347cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return true;
348a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall        }
349cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
350a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall    }
3514d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    if (options_.no_version_transitions) {
3524d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      // Skip this if it is a transition resource.
3534d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      xml::Element* el = xml::FindRootElement(doc);
3544d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      if (el && el->namespace_uri.empty()) {
3554d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki        if (IsTransitionElement(el->name)) {
3564d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          // We are NOT going to version this file.
3574d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          file_op->skip_version = true;
3584d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          return true;
3594d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki        }
3604d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      }
3614d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    }
362a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const ConfigDescription& config = file_op->config;
364cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
365cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Find the first SDK level used that is higher than this defined config and
366cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // not superseded by a lower or equal SDK level resource.
367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const int min_sdk_version = context_->GetMinSdkVersion();
368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (int sdk_level : xml_linker.sdk_levels()) {
369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) {
370d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!ShouldGenerateVersionedResource(file_op->entry, config, sdk_level)) {
371cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // If we shouldn't generate a versioned resource, stop checking.
372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          break;
373626a69f34536d01db0847df0051199beaecce060Adam Lesinski        }
374626a69f34536d01db0847df0051199beaecce060Adam Lesinski
375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ResourceFile versioned_file_desc = doc->file;
376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level;
377cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
378ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        FileOperation new_file_op;
379d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        new_file_op.xml_to_flatten =
380d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            util::make_unique<xml::XmlResource>(versioned_file_desc, doc->root->Clone());
381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_file_op.config = versioned_file_desc.config;
382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_file_op.entry = file_op->entry;
383d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        new_file_op.dst_path =
384d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ResourceUtils::BuildResourceFileName(versioned_file_desc, context_->GetNameMangler());
385cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (context_->IsVerbose()) {
387d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Note(DiagMessage(versioned_file_desc.source)
388d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "auto-versioning resource from config '" << config
389d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "' -> '" << versioned_file_desc.config << "'");
390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        bool added = table->AddFileReferenceAllowMangled(
393d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            versioned_file_desc.name, versioned_file_desc.config, versioned_file_desc.source,
394d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            new_file_op.dst_path, nullptr, context_->GetDiagnostics());
395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (!added) {
396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
39752364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski        }
398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        out_file_op_queue->push(std::move(new_file_op));
400cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        break;
401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
40252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski    }
403cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
404cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
405355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
40652364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
407355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/**
408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Do not insert or remove any resources while executing in this function. It
409cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * will
410355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * corrupt the iteration order.
411355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */
412d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
413cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool error = false;
414d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
416cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  for (auto& pkg : table->packages) {
417cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (auto& type : pkg->types) {
418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Sort by config and name, so that we get better locality in the zip
419cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // file.
420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      config_sorted_files.clear();
421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::queue<FileOperation> file_operations;
422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Populate the queue with all files in the ResourceTable.
424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (auto& entry : type->entries) {
425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& config_value : entry->values) {
426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!file_ref) {
428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            continue;
429cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
430355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          io::IFile* file = file_ref->file;
432cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!file) {
433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource())
434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                              << "file not found");
435cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
437355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          FileOperation file_op;
439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.entry = entry.get();
440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.dst_path = *file_ref->path;
441ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.config = config_value->config;
442355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          const StringPiece src_path = file->GetSource().path;
444cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (type->type != ResourceType::kRaw &&
445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) {
446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            std::unique_ptr<io::IData> data = file->OpenAsData();
447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            if (!data) {
448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
449cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                                << "failed to open file");
450cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
451355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski            }
452355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
453d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(),
454d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  context_->GetDiagnostics(), file->GetSource());
455355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            if (!file_op.xml_to_flatten) {
457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
458a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski            }
459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.config = config_value->config;
461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.source = file_ref->GetSource();
462d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
463cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
464cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            // Enqueue the XML files to be processed.
465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_operations.push(std::move(file_op));
466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          } else {
467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.file_to_copy = file;
468cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
469cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            // NOTE(adamlesinski): Explicitly construct a StringPiece here, or
470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // else we end up copying the string in the std::make_pair() method,
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // then creating a StringPiece from the copy, which would cause us
472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // to end up referencing garbage in the map.
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            const StringPiece entry_name(entry->name);
474d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            config_sorted_files[std::make_pair(config_value->config, entry_name)] =
475d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                std::move(file_op);
476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now process the XML queue
481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (; !file_operations.empty(); file_operations.pop()) {
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        FileOperation& file_op = file_operations.front();
483cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!LinkAndVersionXmlFile(table, &file_op, &file_operations)) {
485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          continue;
487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
488cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // we end up copying the string in the std::make_pair() method, then
491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        // creating a StringPiece from the copy, which would cause us to end up
492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        // referencing garbage in the map.
493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const StringPiece entry_name(file_op.entry->name);
494d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        config_sorted_files[std::make_pair(file_op.config, entry_name)] = std::move(file_op);
495cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
496cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (error) {
498cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now flatten the sorted values.
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (auto& map_entry : config_sorted_files) {
503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const ConfigDescription& config = map_entry.first.first;
504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const FileOperation& file_op = map_entry.second;
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (file_op.xml_to_flatten) {
507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          Maybe<size_t> max_sdk_level;
508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!options_.no_auto_version && !file_op.skip_version) {
509d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            max_sdk_level = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
510d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                             context_->GetMinSdkVersion());
511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
513d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          bool result = FlattenXml(file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level,
514d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   options_.keep_raw_values, archive_writer, context_);
515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!result) {
516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        } else {
519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          bool result =
520d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
521d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                    GetCompressionFlags(file_op.dst_path), archive_writer);
522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!result) {
523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
524cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
5251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
527355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
528cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
529cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return !error;
530355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
531a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
532d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool WriteStableIdMapToPath(IDiagnostics* diag,
533d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::unordered_map<ResourceName, ResourceId>& id_map,
534d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::string& id_map_path) {
535ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::ofstream fout(id_map_path, std::ofstream::binary);
536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(id_map_path) << strerror(errno));
538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
540bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const auto& entry : id_map) {
542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceName& name = entry.first;
543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceId& id = entry.second;
544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    fout << name << " = " << id << "\n";
545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
546bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
548d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
549d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << android::base::SystemErrorCodeToString(errno));
550cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
551cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
552bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
554bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
555bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
556d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
557d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            std::unordered_map<ResourceName, ResourceId>* out_id_map) {
558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string content;
559cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!android::base::ReadFileToString(path, &content)) {
560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << "failed reading stable ID file");
561cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
562cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
563bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  out_id_map->clear();
565ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  size_t line_no = 0;
566ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (StringPiece line : util::Tokenize(content, '\n')) {
567ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line_no++;
568ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line = util::TrimWhitespace(line);
569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (line.empty()) {
570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      continue;
571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
572bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    auto iter = std::find(line.begin(), line.end(), '=');
574cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (iter == line.end()) {
575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "missing '='");
576cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
577cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
578bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ResourceNameRef name;
580ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    StringPiece res_name_str =
581ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
582ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!ResourceUtils::ParseResourceName(res_name_str, &name)) {
583d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str
584d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
587bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
588ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1;
589ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_str_len = line.size() - res_id_start_idx;
590d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));
591bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
592ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str);
593ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_id) {
594d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str
595d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
596cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
597bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski    }
598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    (*out_id_map)[name.ToResourceName()] = maybe_id.value();
600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
602bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
603bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
604355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass LinkCommand {
605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
606cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand(LinkContext* context, const LinkOptions& options)
607ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      : options_(options),
608ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_(context),
609ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        final_table_(),
610d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        file_collection_(util::make_unique<io::FileCollection>()) {
611d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
612cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
613cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
614cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Creates a SymbolTable that loads symbols from the various APKs and caches
615ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the results for faster lookup.
616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool LoadSymbolsFromIncludePaths() {
618ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<AssetManagerSymbolSource> asset_source =
619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        util::make_unique<AssetManagerSymbolSource>();
620ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& path : options_.include_paths) {
621ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
622d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path");
623cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
624cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
625cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // First try to load the file as a static lib.
626ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string error_str;
627ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str);
628ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      if (include_static) {
629ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        if (options_.package_type != PackageType::kStaticLib) {
630ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // Can't include static libraries when not building a static library (they have no IDs
631ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // assigned).
632ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetDiagnostics()->Error(
633ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski              DiagMessage(path) << "can't include static library when not building a static lib");
634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
635cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
63664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
637cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we are using --no-static-lib-packages, we need to rename the
638f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        // package of this table to our compilation package.
639ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_static_lib_packages) {
640f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // Since package names can differ, and multiple packages can exist in a ResourceTable,
641f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // we place the requirement that all static libraries are built with the package
642f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // ID 0x7f. So if one is not found, this is an error.
643f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) {
644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            pkg->name = context_->GetCompilationPackage();
645f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          } else {
646f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(path)
647f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                              << "no package with ID 0x7f found in static library");
648f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            return false;
649cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
650355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski        }
65164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
652ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetExternalSymbols()->AppendSource(
653ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski            util::make_unique<ResourceTableSymbolSource>(include_static.get()));
6541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
655ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        static_table_includes_.push_back(std::move(include_static));
656fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (!error_str.empty()) {
658cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We had an error with reading, so fail.
659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << error_str);
660cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
661cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
662fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
663ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!asset_source->AddAssetPath(path)) {
664ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path");
665cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
666cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
667cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
668fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
669ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // Capture the shared libraries so that the final resource table can be properly flattened
670ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // with support for shared libraries.
671ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    for (auto& entry : asset_source->GetAssignedPackageIds()) {
672f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
673ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        final_table_.included_packages_[entry.first] = entry.second;
674ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
675ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    }
676ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
677ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->AppendSource(std::move(asset_source));
678cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
68036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
681b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski  Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
682cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure the first element is <manifest> with package attribute.
683b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
684b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (manifest_el == nullptr) {
685b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
686b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
68736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
688b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    AppInfo app_info;
689b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
690b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
691b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>");
692b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
693b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
694fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
695b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package");
696b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!package_attr) {
697b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source)
698b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                  << "<manifest> must have a 'package' attribute");
699b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
700b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
701b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    app_info.package = package_attr->value;
702b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
703b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* version_code_attr =
704b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) {
705b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_attr->value);
706b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
707b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
708b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:versionCode '" << version_code_attr->value << "'");
7091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return {};
710cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
711b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.version_code = maybe_code.value();
712b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
714b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* revision_code_attr =
715b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
716b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value);
717b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
718b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
719b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:revisionCode '" << revision_code_attr->value << "'");
720b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        return {};
721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
722b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.revision_code = maybe_code.value();
723b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
725b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) {
726b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!split_name_attr->value.empty()) {
727b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        app_info.split_name = split_name_attr->value;
728cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
729b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
730cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
731b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
732b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (xml::Attribute* min_sdk =
733b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski              uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
734d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value);
735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
737b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    return app_info;
738cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
739cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
740cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
741b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski   * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
742cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Postcondition: ResourceTable has only one package left. All others are
743ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * stripped, or there is an error and false is returned.
744cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
745ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoExternalPackages() {
746d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
747ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
748ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski             pkg->id.value() != context_->GetPackageId();
749cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    };
7501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
751cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
752ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
753ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (is_ext_package_func(package)) {
754cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We have a package that is not related to the one we're building!
755cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& type : package->types) {
756cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (const auto& entry : type->entries) {
757ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
758cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
759ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            for (const auto& config_value : entry->values) {
760cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // Special case the occurrence of an ID that is being generated
761ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              // for the 'android' package. This is due to legacy reasons.
762d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              if (ValueCast<Id>(config_value->value.get()) && package->name == "android") {
763d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource())
764d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "generated id '" << res_name
765d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "' for external package '" << package->name
766d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "'");
767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              } else {
768d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource())
769d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "defined resource '" << res_name
770d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "' for external package '" << package->name
771d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "'");
772cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                error = true;
773cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              }
7741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
775cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
7761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
777cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
778cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
779979ccb2e6f3f1f7f00a448eb440a85daf033dc9eAdam Lesinski
780d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(),
781d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                       is_ext_package_func);
782ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    final_table_.packages.erase(new_end_iter, final_table_.packages.end());
783cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
784cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
785cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
786cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
787cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Returns true if no IDs have been set, false otherwise.
788cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
789ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoIdsSet() {
790ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
791cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (const auto& type : package->types) {
792cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (type->id) {
793f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
794f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << StringPrintf("%02x", type->id.value())
795f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << " assigned");
796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
798cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
799cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& entry : type->entries) {
800cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (entry->id) {
801ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(
803f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                DiagMessage() << "entry " << res_name << " has ID "
804f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                              << StringPrintf("%02x", entry->id.value()) << " assigned");
805cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
80764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        }
808cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
80964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
810cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
811cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
81264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
813ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) {
814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.output_to_directory) {
815ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out);
816cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
817ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out);
8181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
821ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
822cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    BigBuffer buffer(1024);
823c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski    TableFlattener flattener(options_.table_flattener_options, &buffer);
824ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!flattener.Consume(context_, table)) {
82506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
826cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
827cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
8281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
82906460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    io::BigBufferInputStream input_stream(&buffer);
830d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc",
831d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        ArchiveEntry::kAlign, writer);
832cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
833cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
834ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
83506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table);
836d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer);
837cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
839d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
840ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                     const StringPiece& out_package,
841ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                     const JavaClassGeneratorOptions& java_options) {
842ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
843cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
8441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
8451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
846ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(out_package));
848ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
849d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
850d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
851cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
852cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
853ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
854ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "R.java");
855ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
856ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
857cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
858d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
859d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
860d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
862ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski    }
863ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
864ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context_, table, java_options);
865ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!generator.Generate(package_name_to_generate, out_package, &fout)) {
86606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
867cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
868cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
8691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
870cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
871d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
872d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
873d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
8741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
875cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
879ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
880cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
88164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
88264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
883ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<ClassDefinition> manifest_class =
884ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        GenerateManifestClass(context_->GetDiagnostics(), manifest_xml);
88564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_class) {
887cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Something bad happened, but we already logged it, so exit.
888cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
88964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
89064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (manifest_class->empty()) {
892cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Empty Manifest class, no need to generate it.
893cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
89564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
896cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add any JavaDoc annotations to the generated class.
897ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& annotation : options_.javadoc_annotations) {
898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string proper_annotation = "@";
899ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      proper_annotation += annotation;
900ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_class->GetCommentBuilder()->AppendComment(proper_annotation);
901cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
90264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
903ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& package_utf8 = context_->GetCompilationPackage();
90464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
906ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(package_utf8));
90764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
908ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
909d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
910d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
911cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
912cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
91364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
914ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "Manifest.java");
91564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
916ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
917cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
918d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
919d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
920d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
921cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
922cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
92364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
924d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
925d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
927d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
928cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
929cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
930cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
931cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
93264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
933d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
934cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!out) {
935cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
936fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
937fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
938ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& out_path = out.value();
939ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
940cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
941d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed to open '" << out_path
943d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
944cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
946a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
947ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::WriteKeepSet(&fout, keep_set);
948cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
949d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
950d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
951d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
955cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
956fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
957ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input,
958ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                                   std::string* out_error) {
959cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
960ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, out_error);
961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
962cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
964ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTablePbFromCollection(collection.get());
965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
966fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
967d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) {
968ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = collection->FindFile("resources.arsc.flat");
969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!file) {
970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
971fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
972fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
973ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
974ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTableFromPb(file->GetSource(), data->data(), data->size(),
975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           context_->GetDiagnostics());
976cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
977fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
978ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeStaticLibrary(const std::string& input, bool override) {
979ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
980d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
982fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
983ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
984cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
987ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
988cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
989cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
990fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
991b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get());
992cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
993b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library");
994cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
995cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
996cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
997f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!pkg) {
999b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
1000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1001cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1002cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result;
1004ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.no_static_lib_packages) {
1005cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Merge all resources as if they were in the compilation package. This is
1006ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // the old behavior of aapt.
1007cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1008cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Add the package to the set of --extra-packages so we emit an R.java for
1009ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // each library package.
1010cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!pkg->name.empty()) {
1011ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        options_.extra_java_packages.insert(pkg->name);
1012cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1013cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1014cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      pkg->name = "";
1015cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (override) {
1016b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get());
1017cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1018b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->Merge(Source(input), table.get(), collection.get());
1019cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1020cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1021cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1022cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // This is the proper way to merge libraries, where the package name is
1023ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // preserved and resource names are mangled.
1024d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      result =
1025d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get());
1026cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1027cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1028cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1029cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1030cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1032cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1033ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1035cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1036fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeResourceTable(io::IFile* file, bool override) {
1038ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1039d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table "
1040d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1041cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1042fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1043ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
1044cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!data) {
1045d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
1046cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1047cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1048fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1049cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<ResourceTable> table =
1050d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics());
1051cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
1052cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1053fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1054fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1055cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1056cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1057ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeOverlay(file->GetSource(), table.get());
1058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1059ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->Merge(file->GetSource(), table.get());
1060cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1061cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return result;
1062cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
106364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1064d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) {
1065ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1066d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name
1067d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "' from compiled file "
1068d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1070a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1073ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFileOverlay(*file_desc, file);
1074cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFile(*file_desc, file);
1076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1077a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1080cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1081a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the exports of this file to the table.
1083ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) {
1084ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (exported_symbol.name.package.empty()) {
1085ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        exported_symbol.name.package = context_->GetCompilationPackage();
1086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1087a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1088ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ResourceNameRef res_name = exported_symbol.name;
10895eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1090ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Maybe<ResourceName> mangled_name =
1091ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetNameMangler()->MangleName(exported_symbol.name);
1092ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (mangled_name) {
1093ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        res_name = mangled_name.value();
1094cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
109552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
1096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::unique_ptr<Id> id = util::make_unique<Id>();
1097ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      id->SetSource(file_desc->source.WithLine(exported_symbol.line));
1098ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      bool result = final_table_.AddResourceAllowMangled(
1099d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id),
1100d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics());
1101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!result) {
1102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1107cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load as a ZIP file and merges the files within into the
1110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable.
1111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If override is true, conflicting resources are allowed to override each
1112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * other, in order of last seen.
1113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * An io::IFileCollection is created from the ZIP file and added to the set of
1115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * io::IFileCollections that are open.
1116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeArchive(const std::string& input, bool override) {
1118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1119d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
1120fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1121fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
1123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
1125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
1127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
112936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (auto iter = collection->Iterator(); iter->HasNext();) {
1132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergeFile(iter->Next(), override)) {
1133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1134cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
113636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
1140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load and merge into the master ResourceTable. If override
1144cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file path ends with .flata, .jar, .jack, or .zip the file is treated
1149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * as ZIP archive
1150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the files within are merged individually.
1151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Otherwise the files is processed on its own.
1153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergePath(const std::string& path, bool override) {
1155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") ||
1156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) {
1157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeArchive(path, override);
1158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(path, ".apk")) {
1159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeStaticLibrary(path, override);
1160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
1161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = file_collection_->InsertFile(path);
1163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return MergeFile(file, override);
1164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a file to load and merge into the master ResourceTable. If override
1168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and
1173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * merged into the
1174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable. If the file ends with .flat, then it is treated like
1175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * a compiled file
1176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the header data is read and merged into the final ResourceTable.
1177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * All other file types are ignored. This is because these files could be
1179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * coming from a zip,
1180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * where we could have other files like classes.dex.
1181cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeFile(io::IFile* file, bool override) {
1183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const Source& src = file->GetSource();
1184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(src.path, ".arsc.flat")) {
1185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeResourceTable(file, override);
1186cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(src.path, ".flat")) {
1188cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Try opening the file and looking for an Export header.
1189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
1190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!data) {
1191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open");
1192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1193cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
119436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      CompiledFileInputStream input_stream(data->data(), data->size());
1196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      uint32_t num_files = 0;
1197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!input_stream.ReadLittleEndian32(&num_files)) {
1198d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files");
1199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1200cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
120136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (uint32_t i = 0; i < num_files; i++) {
1203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        pb::CompiledFile compiled_file;
1204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadCompiledFile(&compiled_file)) {
1205d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src)
1206d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to read compiled file header");
1207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
120836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
120936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        uint64_t offset, len;
1211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadDataMetaData(&offset, &len)) {
1212d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data");
1213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
121436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
121536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1216d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb(
1217d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            compiled_file, file->GetSource(), context_->GetDiagnostics());
1218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!resource_file) {
1219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
122036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
122136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1222d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(),
1223d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                               override)) {
1224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
122536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1227cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
1228d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
12296a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // Since AAPT compiles these file types and appends .flat to them, seeing
12306a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // their raw extensions is a sign that they weren't compiled.
1231d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
1232d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type
1233d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                         << " file passed as argument. Must be "
1234d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                            "compiled first into .flat file.");
12356a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      return false;
123636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski    }
123736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Ignore non .flat files. This could be classes.dex or something else that
1239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // happens
1240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // to be in an archive.
1241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1244b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  bool CopyAssetsDirsToApk(IArchiveWriter* writer) {
1245b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets;
1246b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (const std::string& assets_dir : options_.assets_dirs) {
1247b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      Maybe<std::vector<std::string>> files =
1248b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr);
1249b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (!files) {
1250b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1251b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1252b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1253b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      for (const std::string& file : files.value()) {
1254b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_key = "assets/" + file;
1255b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_path = assets_dir;
1256b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        file::AppendPath(&full_path, file);
1257b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1258b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        auto iter = merged_assets.find(full_key);
1259b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        if (iter == merged_assets.end()) {
1260b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          merged_assets.emplace(std::move(full_key),
1261b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                util::make_unique<io::RegularFile>(Source(std::move(full_path))));
1262b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        } else if (context_->IsVerbose()) {
1263b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource())
1264b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                           << "asset file overrides '" << full_path << "'");
1265b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        }
1266b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1267b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1268b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1269b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (auto& entry : merged_assets) {
1270b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      uint32_t compression_flags = ArchiveEntry::kCompress;
1271b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      std::string extension = file::GetExtension(entry.first).to_string();
1272b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (options_.extensions_to_not_compress.count(extension) > 0) {
1273b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        compression_flags = 0u;
1274b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1275b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1276d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags,
1277d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                 writer)) {
1278b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1279b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1280b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1281b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    return true;
1282b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  }
1283b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1284cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1285cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Writes the AndroidManifest, ResourceTable, and all XML files referenced by
1286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the ResourceTable to the IArchiveWriter.
1287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1288d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
1289d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                ResourceTable* table) {
1290ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    const bool keep_raw_values = options_.package_type == PackageType::kStaticLib;
1291d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    bool result =
1292d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_);
1293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ResourceFileFlattenerOptions file_flattener_options;
1298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.keep_raw_values = keep_raw_values;
1299d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
1300d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
1301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_auto_version = options_.no_auto_version;
1302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_version_vectors = options_.no_version_vectors;
13034d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    file_flattener_options.no_version_transitions = options_.no_version_transitions;
1304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
1305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.update_proguard_spec =
1306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        static_cast<bool>(options_.generate_proguard_rules_path);
1307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1308ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set);
1309cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_flattener.Flatten(table, writer)) {
1311ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources");
1312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1313cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1314cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1315ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    if (options_.package_type == PackageType::kStaticLib) {
1316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTableToPb(table, writer)) {
1317cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1318cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1319cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTable(table, writer)) {
1321ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc");
1322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1325cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
13279ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
1328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int Run(const std::vector<std::string>& input_files) {
1329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Load the AndroidManifest.xml
1330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> manifest_xml =
1331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LoadXml(options_.manifest_path, context_->GetDiagnostics());
1332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_xml) {
1333cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1336d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    // First extract the Package name without modifying it (via --rename-manifest-package).
1337d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (Maybe<AppInfo> maybe_app_info =
1338d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) {
1339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const AppInfo& app_info = maybe_app_info.value();
1340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetCompilationPackage(app_info.package);
1341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1342fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ManifestFixer manifest_fixer(options_.manifest_fixer_options);
1344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_fixer.Consume(context_, manifest_xml.get())) {
1345cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1346cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1348d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<AppInfo> maybe_app_info =
1349d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics());
1350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_app_info) {
1351cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1352cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const AppInfo& app_info = maybe_app_info.value();
1355d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0));
13561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1357d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});
1358f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1359f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    // Override the package ID when it is "android".
1360f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (context_->GetCompilationPackage() == "android") {
1361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetPackageId(0x01);
1362f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1363f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      // Verify we're building a regular app.
1364f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      if (options_.package_type != PackageType::kApp) {
1365f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        context_->GetDiagnostics()->Error(
1366f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            DiagMessage() << "package 'android' can only be built as a regular app");
1367f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        return 1;
1368f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      }
1369cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadSymbolsFromIncludePaths()) {
1372cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1373cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    TableMergerOptions table_merger_options;
1376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    table_merger_options.auto_add_overlay = options_.auto_add_overlay;
1377d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);
13781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage()
1381f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                       << StringPrintf("linking package '%s' using package ID %02x",
1382f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetCompilationPackage().data(),
1383f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetPackageId()));
1384cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1385bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : input_files) {
1387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, false)) {
1388d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input");
1389cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1390cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
13921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : options_.overlay_files) {
1394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, true)) {
1395d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays");
1396cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1397cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
139964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!VerifyNoExternalPackages()) {
1401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1404ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    if (options_.package_type != PackageType::kStaticLib) {
1405cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      PrivateAttributeMover mover;
1406ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!mover.Consume(context_, &final_table_)) {
1407d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes");
1408cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1409cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
141036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1411cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Assign IDs if we are building a regular app.
1412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      IdAssigner id_assigner(&options_.stable_id_map);
1413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!id_assigner.Consume(context_, &final_table_)) {
1414ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs");
1415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1416cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
141736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1418cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now grab each ID and emit it as a file.
1419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.resource_id_map_path) {
1420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& package : final_table_.packages) {
1421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (auto& type : package->types) {
1422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            for (auto& entry : type->entries) {
1423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              ResourceName name(package->name, type->type, entry->name);
1424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // The IDs are guaranteed to exist.
1425d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              options_.stable_id_map[std::move(name)] =
1426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                  ResourceId(package->id.value(), type->id.value(), entry->id.value());
14271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
1428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
142936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
143036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1431d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map,
1432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                    options_.resource_id_map_path.value())) {
1433cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
143436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1435cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1436cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1437cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Static libs are merged with other apps, and ID collisions are bad, so
1438cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // verify that
1439cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // no IDs have been set.
1440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!VerifyNoIdsSet()) {
1441cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1443cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1444cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1445cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the names to mangle based on our source merge earlier.
1446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(
1447d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()});
1448cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1449cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add our table to the symbol table.
1450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->PrependSource(
1451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::make_unique<ResourceTableSymbolSource>(&final_table_));
1452cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ReferenceLinker linker;
1454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!linker.Consume(context_, &final_table_)) {
1455d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references");
1456cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1459ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    if (options_.package_type == PackageType::kStaticLib) {
1460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!options_.products.empty()) {
1461ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1462ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't select products when building static library");
1463cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1464cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ProductFilter product_filter(options_.products);
1466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!product_filter.Consume(context_, &final_table_)) {
1467ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products");
1468cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1469cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
147136c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_auto_version) {
1473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      AutoVersioner versioner;
1474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!versioner.Consume(context_, &final_table_)) {
1475d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles");
1476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
147977788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall
1480ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    if (options_.package_type != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) {
1481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
1482d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage()
1483d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << "collapsing resource versions for minimum SDK "
1484d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << context_->GetMinSdkVersion());
1485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
148636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      VersionCollapser collapser;
1488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!collapser.Consume(context_, &final_table_)) {
1489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1492355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_resource_deduping) {
1494cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      ResourceDeduper deduper;
1495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!deduper.Consume(context_, &final_table_)) {
1496ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
1497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1498cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1500cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_keep_set;
1502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_main_dex_keep_set;
1503cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1504ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    if (options_.package_type == PackageType::kStaticLib) {
1505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.table_splitter_options.config_filter != nullptr ||
1506672384b41e1fc7195424533b7aa6753fb771a6cbPierre Lecesne          !options_.table_splitter_options.preferred_densities.empty()) {
1507ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1508ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't strip resources when building static library");
1509cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1511d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
1512d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // equal to the minSdk.
1513d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      options_.split_constraints =
1514d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
1515cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1516d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
1517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!table_splitter.VerifySplitConstraints(context_)) {
1518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1519cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      table_splitter.SplitTable(&final_table_);
1521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now we need to write out the Split APKs.
1523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      auto path_iter = options_.split_paths.begin();
1524d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      auto split_constraints_iter = options_.split_constraints.begin();
1525d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) {
1526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (context_->IsVerbose()) {
1527d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Note(DiagMessage(*path_iter)
1528d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "generating split with configurations '"
1529d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << util::Joiner(split_constraints_iter->configs, ", ")
1530d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "'");
15311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
15321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1533d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter);
1534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!archive_writer) {
1535d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
15371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
15381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Generate an AndroidManifest.xml for each split.
1540ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<xml::XmlResource> split_manifest =
1541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            GenerateSplitManifest(app_info, *split_constraints_iter);
15421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        XmlReferenceLinker linker;
1544ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!linker.Consume(context_, split_manifest.get())) {
1545d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage()
1546d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to create Split AndroidManifest.xml");
1547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1548467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        }
1549467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
1550d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(),
1551d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                      split_table.get())) {
1552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1553637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall        }
1554637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall
1555ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++path_iter;
1556ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++split_constraints_iter;
1557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
15599e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1560cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Start writing the base APK.
1561b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(options_.output_path);
1562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!archive_writer) {
1563b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1564cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1565cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
15669e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    {
1569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // AndroidManifest.xml has no resource name, but the CallSite is built
1570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // from the name
1571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // (aka, which package the AndroidManifest.xml is coming from).
1572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // So we give it a package name so it can see local resources.
1573ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_xml->file.name.package = context_->GetCompilationPackage();
1574ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      XmlReferenceLinker manifest_linker;
1576ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (manifest_linker.Consume(context_, manifest_xml.get())) {
1577ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_proguard_rules_path &&
1578b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1579b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(), &proguard_keep_set)) {
1580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
15811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
15821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1583ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_main_dex_proguard_rules_path &&
1584b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1585b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(),
1586b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       &proguard_main_dex_keep_set, true)) {
1587cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
1588e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal        }
1589e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal
1590ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_java_class_path) {
1591ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!WriteManifestJavaFile(manifest_xml.get())) {
1592cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1593cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
15941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
15951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1596ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_xml_namespaces) {
1597cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // PackageParser will fail if URIs are removed from
1598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // AndroidManifest.xml.
1599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          XmlNamespaceRemover namespace_remover(true /* keepUris */);
1600ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!namespace_remover.Consume(context_, manifest_xml.get())) {
1601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1602cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
16031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1606cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
16071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1608fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1609cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (error) {
1610b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed processing manifest");
1611cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1612cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1613a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski
1614b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) {
1615b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      return 1;
1616b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1617b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1618b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!CopyAssetsDirsToApk(archive_writer.get())) {
1619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1620cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1621fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.generate_java_class_path) {
1623b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // The set of packages whose R class to call in the main classes
1624b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // onResourcesLoaded callback.
1625b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      std::vector<std::string> packages_to_callback;
1626b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1627b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions template_options;
1628b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1629b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.javadoc_annotations = options_.javadoc_annotations;
1630fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1631ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      if (options_.package_type == PackageType::kStaticLib || options_.generate_non_final_ids) {
1632b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1633ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
1634ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1635ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      if (options_.package_type == PackageType::kSharedLib) {
1636b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1637b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
1638cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
163964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1640ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const StringPiece actual_package = context_->GetCompilationPackage();
1641ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      StringPiece output_package = context_->GetCompilationPackage();
1642ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.custom_java_package) {
1643cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Override the output java package to the custom one.
1644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        output_package = options_.custom_java_package.value();
1645cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
16461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1647b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the private symbols if required.
1648ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.private_symbols) {
1649b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(options_.private_symbols.value());
1650b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1651cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we defined a private symbols package, we only emit Public symbols
1652cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // to the original package, and private and public symbols to the
1653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // private package.
1654b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1655b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
1656b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
1657b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski                           options)) {
1658b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski          return 1;
1659b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        }
1660b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
16611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1662b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate all the symbols for all extra packages.
1663b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      for (const std::string& extra_package : options_.extra_java_packages) {
1664b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(extra_package);
1665b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1666b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1667b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1668b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
1669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1670c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski        }
1671b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
16721e21ff00b005110128245a4b0d13a7513a2d5e0cAdam Lesinski
1673b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the main public R class.
1674b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions options = template_options;
1675b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1676b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Only generate public symbols if we have a private package.
1677b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options_.private_symbols) {
1678b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
1679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1680c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski
1681b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options.rewrite_callback_options) {
1682b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.rewrite_callback_options.value().packages_to_callback =
1683b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski            std::move(packages_to_callback);
1684cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
168564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1686b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (!WriteJavaFile(&final_table_, actual_package, output_package, options)) {
1687b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        return 1;
1688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1689fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski    }
1690fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1691b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) {
1692cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1693e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski    }
1694e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski
1695ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path,
1696ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           proguard_main_dex_keep_set)) {
1697cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1698cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1699cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
1700cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1701355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
1703ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkOptions options_;
1704ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkContext* context_;
1705ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceTable final_table_;
1706355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1707ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<TableMerger> table_merger_;
1708355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1709cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A pointer to the FileCollection representing the filesystem (not archives).
1710ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<io::FileCollection> file_collection_;
17116a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski
1712cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of IFileCollections. This is mainly here to keep ownership of the
1713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // collections.
1714ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<io::IFileCollection>> collections_;
1715bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1716cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of ResourceTables. This is here to retain ownership, so that the
1717ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // SymbolTable can use these.
1718ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<ResourceTable>> static_table_includes_;
1719ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1720ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // The set of shared libraries being used, mapping their assigned package ID to package name.
1721ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::map<size_t, std::string> shared_libs_;
1722cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski};
172336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1724ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Link(const std::vector<StringPiece>& args) {
1725cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkContext context;
1726cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkOptions options;
1727ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_arg_list;
1728ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> extra_java_packages;
1729f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  Maybe<std::string> package_id;
1730113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski  std::vector<std::string> configs;
1731ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> preferred_density;
1732ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> product_list;
1733ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool legacy_x_flag = false;
1734ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool require_localization = false;
1735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool verbose = false;
1736ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool shared_lib = false;
1737ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool static_lib = false;
1738ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> stable_id_file_path;
1739ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_args;
1740cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Flags flags =
1741cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      Flags()
1742d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("-o", "Output path.", &options.output_path)
1743d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("--manifest", "Path to the Android manifest to build.",
1744ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_path)
1745d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths)
1746b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          .OptionalFlagList("-A",
1747b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            "An assets directory to include in the APK. These are unprocessed.",
1748b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            &options.assets_dirs)
1749c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("-R",
1750c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "Compilation unit to link, using `overlay` semantics.\n"
1751c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "The last conflicting resource given takes precedence.",
1752c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &overlay_arg_list)
1753f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          .OptionalFlag("--package-id",
1754f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "Specify the package ID to use for this app. Must be greater or equal to\n"
1755f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "0x7f and can't be used with --static-lib or --shared-lib.",
1756f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        &package_id)
1757d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--java", "Directory in which to generate R.java.",
1758ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_java_class_path)
1759d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--proguard", "Output file for generated Proguard rules.",
1760ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_proguard_rules_path)
1761c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--proguard-main-dex",
1762d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Output file for generated Proguard rules for the main dex.",
1763c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.generate_main_dex_proguard_rules_path)
1764d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--no-auto-version",
1765d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic style and layout SDK versioning.",
1766ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_auto_version)
1767ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-version-vectors",
1768d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of vector drawables. Use this only\n"
1769d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with vector drawable support library.",
1770ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_version_vectors)
17714d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          .OptionalSwitch("--no-version-transitions",
1772d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of transition resources. Use this only\n"
1773d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with transition support library.",
17744d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki                          &options.no_version_transitions)
1775ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-resource-deduping",
1776cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "Disables automatic deduping of resources with\n"
1777cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "identical values across compatible configurations.",
1778ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_resource_deduping)
1779c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalSwitch("--enable-sparse-encoding",
1780c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "Enables encoding sparse entries using a binary search tree.\n"
1781c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "This decreases APK size at the cost of resource retrieval performance.",
1782c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &options.table_flattener_options.use_sparse_entries)
1783d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
1784c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &legacy_x_flag)
1785d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
1786ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &require_localization)
1787113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski          .OptionalFlagList("-c",
1788c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        "Comma separated list of configurations to include. The default\n"
1789d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "is all configurations.",
1790c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &configs)
1791c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--preferred-density",
1792c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        "Selects the closest matching density and strips out all others.",
1793c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &preferred_density)
1794c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
1795ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--output-to-dir",
1796d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Outputs the APK contents to a directory specified by -o.",
1797ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.output_to_directory)
1798ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-xml-namespaces",
1799d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Removes XML namespace prefix and URI information from\n"
1800d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "AndroidManifest.xml and XML binaries in res/*.",
1801ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_xml_namespaces)
1802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--min-sdk-version",
1803d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default minimum SDK version to use for AndroidManifest.xml.",
1804ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.min_sdk_version_default)
1805c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--target-sdk-version",
1806d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default target SDK version to use for AndroidManifest.xml.",
1807c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.target_sdk_version_default)
1808ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-code",
1809d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
1810d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "present.",
1811ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_code_default)
1812ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-name",
1813d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version name to inject into the AndroidManifest.xml if none is present.",
1814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_name_default)
1815d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
1816d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          &shared_lib)
1817d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
1818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-static-lib-packages",
1819d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Merge all library resources under the app's package.",
1820ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_static_lib_packages)
1821ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--non-final-ids",
1822d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Generates R.java without the final modifier. This is implied when\n"
1823d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "--static-lib is specified.",
1824ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.generate_non_final_ids)
1825c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
1826ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &stable_id_file_path)
1827c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--emit-ids",
1828d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Emit a file at the given path with a list of name to ID mappings,\n"
1829d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "suitable for use with --stable-ids.",
1830c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.resource_id_map_path)
1831ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--private-symbols",
1832d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Package name to use when generating R.java for private symbols.\n"
1833d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "If not specified, public and private symbols will use the application's\n"
1834d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "package name.",
1835ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.private_symbols)
1836d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
1837ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.custom_java_package)
1838ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--extra-packages",
1839d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Generate the same R.java but with different package names.",
1840ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &extra_java_packages)
1841ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--add-javadoc-annotation",
1842d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Adds a JavaDoc annotation to all generated Java classes.",
1843ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.javadoc_annotations)
1844ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--auto-add-overlay",
1845d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Allows the addition of new resources in overlays without\n"
1846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "<add-resource> tags.",
1847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.auto_add_overlay)
1848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
1849ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.rename_manifest_package)
1850c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--rename-instrumentation-target-package",
1851d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Changes the name of the target package for instrumentation. Most useful\n"
1852d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "when used in conjunction with --rename-manifest-package.",
1853c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.rename_instrumentation_target_package)
1854d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-0", "File extensions not to compress.",
1855ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.extensions_to_not_compress)
1856c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("--split",
1857d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Split resources matching a set of configs out to a Split APK.\n"
1858d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Syntax: path/to/output.apk:<config>[,<config>[...]].",
1859c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &split_args)
1860d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
1861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1862ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flags.Parse("aapt2 link", args, &std::cerr)) {
1863cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 1;
1864cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1865cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1866d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Expand all argument-files passed into the command line. These start with '@'.
1867ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> arg_list;
1868ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : flags.GetArgs()) {
1869ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1870cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1871cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1872ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &arg_list, &error)) {
1873ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1874cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1875cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1877ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      arg_list.push_back(arg);
1878cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1879cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1880cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1881cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Expand all argument-files passed to -R.
1882ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : overlay_arg_list) {
1883ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1884cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1885cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) {
1887ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1888cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1889cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1890cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      options.overlay_files.push_back(arg);
1892cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1893cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1895cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (verbose) {
1896ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context.SetVerbose(verbose);
1897cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1898cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1899f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib && static_lib) {
1900f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.GetDiagnostics()->Error(DiagMessage()
1901f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                    << "only one of --shared-lib and --static-lib can be defined");
1902f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    return 1;
1903f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
1904f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1905f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib) {
1906f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    options.package_type = PackageType::kSharedLib;
1907f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(0x00);
1908f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else if (static_lib) {
1909f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    options.package_type = PackageType::kStaticLib;
1910f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
1911f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else {
1912f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    options.package_type = PackageType::kApp;
1913f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
1914f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
1915f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1916f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (package_id) {
1917f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (options.package_type != PackageType::kApp) {
1918f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
1919f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << "can't specify --package-id when not building a regular app");
1920f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
1921f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
1922f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1923f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
1924f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (!maybe_package_id_int) {
1925f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
1926f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                    << "' is not a valid integer");
1927f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
1928f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
1929f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1930f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const uint32_t package_id_int = maybe_package_id_int.value();
1931f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
1932f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
1933f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << StringPrintf(
1934f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski              "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
1935f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
1936f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
1937f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(static_cast<uint8_t>(package_id_int));
1938f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
1939f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1940cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate the set of extra packages for which to generate R.java.
1941ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (std::string& extra_package : extra_java_packages) {
1942cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // A given package can actually be a colon separated list of packages.
1943ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece package : util::Split(extra_package, ':')) {
1944d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski      options.extra_java_packages.insert(package.to_string());
1945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1946cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1947cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1948ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (product_list) {
1949ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
1950cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (product != "" && product != "default") {
1951d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski        options.products.insert(product.to_string());
1952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1955cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1956d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<IConfigFilter> filter;
1957f4dacf29cc995fad4aea8e8f25811f9ee4685d91Mihai Nita  if (!configs.empty()) {
1958d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
1959d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (filter == nullptr) {
1960d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      return 1;
1961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1962d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.config_filter = filter.get();
1963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1964cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1965ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (preferred_density) {
1966d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<uint16_t> density =
1967d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics());
1968d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!density) {
1969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1971d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.preferred_densities.push_back(density.value());
1972d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1973cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1974d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Parse the split parameters.
1975d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  for (const std::string& split_arg : split_args) {
1976d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_paths.push_back({});
1977d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_constraints.push_back({});
1978d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
1979d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                             &options.split_constraints.back())) {
1980cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1984ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  if (options.package_type != PackageType::kStaticLib && stable_id_file_path) {
1985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
1986ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                         &options.stable_id_map)) {
1987cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1988cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1989cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1990cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1991cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate some default no-compress extensions that are already compressed.
1992ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.extensions_to_not_compress.insert(
1993cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
1994cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
1995cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
1996cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
1997cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Turn off auto versioning for static-libs.
1999ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  if (options.package_type == PackageType::kStaticLib) {
2000ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_auto_version = true;
2001ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_version_vectors = true;
20024d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    options.no_version_transitions = true;
2003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2004cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2005cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand cmd(&context, options);
2006ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return cmd.Run(arg_list);
20071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
20081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2009cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
2010