Link.cpp revision 1e4b0e54a3db31bdbcb9385bf22bab4b96096d1f
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
681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct LinkOptions {
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output_path;
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string manifest_path;
71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> include_paths;
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_files;
73b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  std::vector<std::string> assets_dirs;
74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool output_to_directory = false;
75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool auto_add_overlay = false;
76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Java/Proguard options.
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_java_class_path;
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> custom_java_package;
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::set<std::string> extra_java_packages;
81418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski  Maybe<std::string> generate_text_symbols_path;
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_proguard_rules_path;
83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_main_dex_proguard_rules_path;
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool generate_non_final_ids = false;
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> javadoc_annotations;
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> private_symbols;
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Optimizations/features.
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
914d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_resource_deduping = false;
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Static lib options.
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_static_lib_packages = false;
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // AndroidManifest.xml massaging options.
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ManifestFixerOptions manifest_fixer_options;
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Products to use/filter on.
104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unordered_set<std::string> products;
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
106c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  // Flattening options.
107c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  TableFlattenerOptions table_flattener_options;
108c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski
109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Split APK options.
110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  TableSplitterOptions table_splitter_options;
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<SplitConstraints> split_constraints;
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_paths;
113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Stable ID options.
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_map<ResourceName, ResourceId> stable_id_map;
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> resource_id_map_path;
1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
11964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass LinkContext : public IAaptContext {
120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
121d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  LinkContext() : name_mangler_({}), symbols_(&name_mangler_) {
122d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
124b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType GetPackageType() override {
125b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    return package_type_;
126b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
127b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski
128b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  void SetPackageType(PackageType type) {
129b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    package_type_ = type;
130b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
131b522f04bc2a581e2877bef4a44ac00b827f879edAdam 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
183b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType package_type_ = PackageType::kApp;
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  StdErrDiagnostics diagnostics_;
185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  NameMangler name_mangler_;
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string compilation_package_;
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint8_t package_id_ = 0x0;
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SymbolTable symbols_;
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool verbose_ = false;
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int min_sdk_version_ = 0;
1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1931e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// A custom delegate that generates compatible pre-O IDs for use with feature splits.
1941e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// Feature splits use package IDs > 7f, which in Java (since Java doesn't have unsigned ints)
1951e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// is interpreted as a negative number. Some verification was wrongly assuming negative values
1961e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// were invalid.
1971e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski//
1981e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE,
1991e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such
2001e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// an overlap exists.
2011e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinskiclass FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
2021e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski public:
2031e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
2041e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  }
2051e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2061e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  virtual ~FeatureSplitSymbolTableDelegate() = default;
2071e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2081e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
2091e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      const ResourceName& name,
2101e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      const std::vector<std::unique_ptr<ISymbolSource>>& sources) override {
2111e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    std::unique_ptr<SymbolTable::Symbol> symbol =
2121e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        DefaultSymbolTableDelegate::FindByName(name, sources);
2131e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (symbol == nullptr) {
2141e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      return {};
2151e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
2161e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2171e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // Check to see if this is an 'id' with the target package.
2181e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (name.type == ResourceType::kId && symbol->id) {
2191e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      ResourceId* id = &symbol->id.value();
2201e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      if (id->package_id() > kAppPackageId) {
2211e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        // Rewrite the resource ID to be compatible pre-O.
2221e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        ResourceId rewritten_id(kAppPackageId, id->package_id(), id->entry_id());
2231e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2241e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        // Check that this doesn't overlap another resource.
2251e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        if (DefaultSymbolTableDelegate::FindById(rewritten_id, sources) != nullptr) {
2261e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          // The ID overlaps, so log a message (since this is a weird failure) and fail.
2271e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "Failed to rewrite " << name
2281e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                                          << " for pre-O feature split support");
2291e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          return {};
2301e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        }
2311e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2321e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        if (context_->IsVerbose()) {
2331e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          context_->GetDiagnostics()->Note(DiagMessage() << "rewriting " << name << " (" << *id
2341e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                                         << ") -> (" << rewritten_id << ")");
2351e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        }
2361e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2371e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        *id = rewritten_id;
2381e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      }
2391e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
2401e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    return symbol;
2411e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  }
2421e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2431e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski private:
2441e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  DISALLOW_COPY_AND_ASSIGN(FeatureSplitSymbolTableDelegate);
2451e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2461e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  IAaptContext* context_;
2471e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski};
2481e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path,
250d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                       Maybe<size_t> max_sdk_level, bool keep_raw_values, IArchiveWriter* writer,
251d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                       IAaptContext* context) {
252cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  BigBuffer buffer(1024);
253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattenerOptions options = {};
254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.keep_raw_values = keep_raw_values;
255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.max_sdk_level = max_sdk_level;
256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattener flattener(&buffer, options);
257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flattener.Consume(context, xml_res)) {
258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (context->IsVerbose()) {
262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    DiagMessage msg;
263cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    msg << "writing " << path << " to archive";
264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (max_sdk_level) {
265d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      msg << " maxSdkLevel=" << max_sdk_level.value() << " keepRawValues=" << keep_raw_values;
266355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context->GetDiagnostics()->Note(msg);
268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
26959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
27006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  io::BigBufferInputStream input_stream(&buffer);
271d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
272d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                      ArchiveEntry::kCompress, writer);
273355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
27459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
275d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data,
276d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      size_t len, IDiagnostics* diag) {
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  pb::ResourceTable pb_table;
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!pb_table.ParseFromArray(data, len)) {
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(source) << "invalid compiled table");
280cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
28306460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::unique_ptr<ResourceTable> table = DeserializeTableFromPb(pb_table, source, diag);
284cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!table) {
285cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
286cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return table;
288355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
2891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
290355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/**
291355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Inflates an XML file from the source path.
292355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */
293d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::ifstream fin(path, std::ifstream::binary);
295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fin) {
296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << strerror(errno));
297cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
298cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return xml::Inflate(&fin, diag, Source(path));
300355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
302355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistruct ResourceFileFlattenerOptions {
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
3054d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool keep_raw_values = false;
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool update_proguard_spec = false;
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
311355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
312355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
313355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass ResourceFileFlattener {
314cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
315d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context,
316d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        proguard::KeepSet* keep_set)
317d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      : options_(options), context_(context), keep_set_(keep_set) {
318d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
3191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer);
321355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  struct FileOperation {
324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ConfigDescription config;
3255eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The entry this file came from.
327cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceEntry* entry;
3285eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The file to copy as-is.
330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file_to_copy;
3315eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
332cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The XML to process and flatten.
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> xml_to_flatten;
3345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
335cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The destination to write this file to.
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string dst_path;
337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool skip_version = false;
338cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  };
339355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint32_t GetCompressionFlags(const StringPiece& str);
341355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                             std::queue<FileOperation>* out_file_op_queue);
344355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceFileFlattenerOptions options_;
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  IAaptContext* context_;
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  proguard::KeepSet* keep_set_;
348355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
349355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiuint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.do_not_compress_anything) {
352cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
354355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& extension : options_.extensions_to_not_compress) {
356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(str, extension)) {
357cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 0;
358355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
359cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
360cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return ArchiveEntry::kCompress;
361355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
362355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
3634d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const std::string& name) {
364d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
365d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeImageTransform" || name == "changeTransform" ||
366d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
367d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeScroll" || name == "transitionSet" || name == "transition" ||
368d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "transitionManager";
3694d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki}
3704d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki
371d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
372d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  std::queue<FileOperation>* out_file_op_queue) {
373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* doc = file_op->xml_to_flatten.get();
374cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const Source& src = doc->file.source;
375355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (context_->IsVerbose()) {
377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path);
378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
379355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XmlReferenceLinker xml_linker;
381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!xml_linker.Consume(context_, doc)) {
382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
384355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
385d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) {
386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.no_xml_namespaces) {
390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    XmlNamespaceRemover namespace_remover;
391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!namespace_remover.Consume(context_, doc)) {
392cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
393355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
395355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!options_.no_auto_version) {
397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.no_version_vectors) {
398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Skip this if it is a vector or animated-vector.
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      xml::Element* el = xml::FindRootElement(doc);
400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (el && el->namespace_uri.empty()) {
401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (el->name == "vector" || el->name == "animated-vector") {
402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // We are NOT going to version this file.
403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op->skip_version = true;
404cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return true;
405a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall        }
406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
407a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall    }
4084d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    if (options_.no_version_transitions) {
4094d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      // Skip this if it is a transition resource.
4104d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      xml::Element* el = xml::FindRootElement(doc);
4114d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      if (el && el->namespace_uri.empty()) {
4124d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki        if (IsTransitionElement(el->name)) {
4134d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          // We are NOT going to version this file.
4144d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          file_op->skip_version = true;
4154d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          return true;
4164d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki        }
4174d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki      }
4184d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    }
419a7cc3f1d79eb7a02a68928381998137f2f9b10a3Alexandria Cornwall
420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const ConfigDescription& config = file_op->config;
421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Find the first SDK level used that is higher than this defined config and
423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // not superseded by a lower or equal SDK level resource.
424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const int min_sdk_version = context_->GetMinSdkVersion();
425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (int sdk_level : xml_linker.sdk_levels()) {
426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) {
427d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!ShouldGenerateVersionedResource(file_op->entry, config, sdk_level)) {
428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // If we shouldn't generate a versioned resource, stop checking.
429cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          break;
430626a69f34536d01db0847df0051199beaecce060Adam Lesinski        }
431626a69f34536d01db0847df0051199beaecce060Adam Lesinski
432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ResourceFile versioned_file_desc = doc->file;
433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level;
434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        FileOperation new_file_op;
436ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski        new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>(
437ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski            versioned_file_desc, StringPool{}, doc->root->Clone());
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_file_op.config = versioned_file_desc.config;
439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_file_op.entry = file_op->entry;
440d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        new_file_op.dst_path =
441d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ResourceUtils::BuildResourceFileName(versioned_file_desc, context_->GetNameMangler());
442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (context_->IsVerbose()) {
444d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Note(DiagMessage(versioned_file_desc.source)
445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "auto-versioning resource from config '" << config
446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "' -> '" << versioned_file_desc.config << "'");
447cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
448cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        bool added = table->AddFileReferenceAllowMangled(
450d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            versioned_file_desc.name, versioned_file_desc.config, versioned_file_desc.source,
451d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            new_file_op.dst_path, nullptr, context_->GetDiagnostics());
452cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (!added) {
453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
45452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski        }
455cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        out_file_op_queue->push(std::move(new_file_op));
457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        break;
458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
45952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski    }
460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
461cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
462355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
46352364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
464355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/**
465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Do not insert or remove any resources while executing in this function. It
466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * will
467355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * corrupt the iteration order.
468355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */
469d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool error = false;
471d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
472cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
473cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  for (auto& pkg : table->packages) {
474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (auto& type : pkg->types) {
475cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Sort by config and name, so that we get better locality in the zip
476cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // file.
477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      config_sorted_files.clear();
478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::queue<FileOperation> file_operations;
479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Populate the queue with all files in the ResourceTable.
481cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (auto& entry : type->entries) {
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& config_value : entry->values) {
483d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!file_ref) {
485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            continue;
486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
487355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          io::IFile* file = file_ref->file;
489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!file) {
490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource())
491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                              << "file not found");
492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
494355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          FileOperation file_op;
496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.entry = entry.get();
497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.dst_path = *file_ref->path;
498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.config = config_value->config;
499355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          const StringPiece src_path = file->GetSource().path;
501cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (type->type != ResourceType::kRaw &&
502d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) {
503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            std::unique_ptr<io::IData> data = file->OpenAsData();
504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            if (!data) {
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                                << "failed to open file");
507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
508355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski            }
509355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
510d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(),
511d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  context_->GetDiagnostics(), file->GetSource());
512355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            if (!file_op.xml_to_flatten) {
514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
515a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski            }
516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.config = config_value->config;
518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.source = file_ref->GetSource();
519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
520cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            // Enqueue the XML files to be processed.
522ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_operations.push(std::move(file_op));
523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          } else {
524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.file_to_copy = file;
525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            // NOTE(adamlesinski): Explicitly construct a StringPiece here, or
527ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // else we end up copying the string in the std::make_pair() method,
528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // then creating a StringPiece from the copy, which would cause us
529ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            // to end up referencing garbage in the map.
530ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            const StringPiece entry_name(entry->name);
531d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            config_sorted_files[std::make_pair(config_value->config, entry_name)] =
532d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                std::move(file_op);
533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
534cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
537cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now process the XML queue
538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (; !file_operations.empty(); file_operations.pop()) {
539ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        FileOperation& file_op = file_operations.front();
540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
541ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!LinkAndVersionXmlFile(table, &file_op, &file_operations)) {
542cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          continue;
544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
546cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
547cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // we end up copying the string in the std::make_pair() method, then
548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        // creating a StringPiece from the copy, which would cause us to end up
549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        // referencing garbage in the map.
550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const StringPiece entry_name(file_op.entry->name);
551d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        config_sorted_files[std::make_pair(file_op.config, entry_name)] = std::move(file_op);
552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
554cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (error) {
555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
556cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now flatten the sorted values.
559ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (auto& map_entry : config_sorted_files) {
560ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const ConfigDescription& config = map_entry.first.first;
561ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const FileOperation& file_op = map_entry.second;
562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (file_op.xml_to_flatten) {
564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          Maybe<size_t> max_sdk_level;
565ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!options_.no_auto_version && !file_op.skip_version) {
566d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            max_sdk_level = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
567d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                             context_->GetMinSdkVersion());
568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
570d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          bool result = FlattenXml(file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level,
571d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   options_.keep_raw_values, archive_writer, context_);
572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!result) {
573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
574cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
575cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        } else {
576d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          bool result =
577d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
578d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                    GetCompressionFlags(file_op.dst_path), archive_writer);
579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!result) {
580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
5821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
583cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
584355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return !error;
587355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
588a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
589d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool WriteStableIdMapToPath(IDiagnostics* diag,
590d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::unordered_map<ResourceName, ResourceId>& id_map,
591d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::string& id_map_path) {
592ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::ofstream fout(id_map_path, std::ofstream::binary);
593cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
594ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(id_map_path) << strerror(errno));
595cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
596cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
597bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
598ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const auto& entry : id_map) {
599cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceName& name = entry.first;
600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceId& id = entry.second;
601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    fout << name << " = " << id << "\n";
602cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
603bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
605d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
606d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << android::base::SystemErrorCodeToString(errno));
607cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
608cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
609bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
610cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
611bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
612bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
613d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
614d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            std::unordered_map<ResourceName, ResourceId>* out_id_map) {
615cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string content;
616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!android::base::ReadFileToString(path, &content)) {
617ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << "failed reading stable ID file");
618cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
620bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
621ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  out_id_map->clear();
622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  size_t line_no = 0;
623ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (StringPiece line : util::Tokenize(content, '\n')) {
624ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line_no++;
625ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line = util::TrimWhitespace(line);
626cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (line.empty()) {
627cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      continue;
628cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
629bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
630cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    auto iter = std::find(line.begin(), line.end(), '=');
631cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (iter == line.end()) {
632ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "missing '='");
633cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
635bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
636cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ResourceNameRef name;
637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    StringPiece res_name_str =
638ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
639ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!ResourceUtils::ParseResourceName(res_name_str, &name)) {
640d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str
641d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
642cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
643cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
644bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1;
646ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_str_len = line.size() - res_id_start_idx;
647d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));
648bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
649ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str);
650ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_id) {
651d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str
652d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
654bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski    }
655cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
656ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    (*out_id_map)[name.ToResourceName()] = maybe_id.value();
657cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
658cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
659bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
660bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
661355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass LinkCommand {
662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
663cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand(LinkContext* context, const LinkOptions& options)
664ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      : options_(options),
665ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_(context),
666ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        final_table_(),
667d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        file_collection_(util::make_unique<io::FileCollection>()) {
668d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
670cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
671cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Creates a SymbolTable that loads symbols from the various APKs and caches
672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the results for faster lookup.
673cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
674ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool LoadSymbolsFromIncludePaths() {
675ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<AssetManagerSymbolSource> asset_source =
676cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        util::make_unique<AssetManagerSymbolSource>();
677ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& path : options_.include_paths) {
678ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
679d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path");
680cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
681cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
682cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // First try to load the file as a static lib.
683ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string error_str;
684ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str);
685ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      if (include_static) {
686b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski        if (context_->GetPackageType() != PackageType::kStaticLib) {
687ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // Can't include static libraries when not building a static library (they have no IDs
688ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // assigned).
689ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetDiagnostics()->Error(
690ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski              DiagMessage(path) << "can't include static library when not building a static lib");
691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
692cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
69364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
694cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we are using --no-static-lib-packages, we need to rename the
695f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        // package of this table to our compilation package.
696ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_static_lib_packages) {
697f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // Since package names can differ, and multiple packages can exist in a ResourceTable,
698f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // we place the requirement that all static libraries are built with the package
699f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // ID 0x7f. So if one is not found, this is an error.
700f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) {
701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            pkg->name = context_->GetCompilationPackage();
702f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          } else {
703f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(path)
704f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                              << "no package with ID 0x7f found in static library");
705f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            return false;
706cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
707355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski        }
70864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
709ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetExternalSymbols()->AppendSource(
710ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski            util::make_unique<ResourceTableSymbolSource>(include_static.get()));
7111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
712ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        static_table_includes_.push_back(std::move(include_static));
713fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
714ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (!error_str.empty()) {
715cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We had an error with reading, so fail.
716ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << error_str);
717cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
718cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
719fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
720ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!asset_source->AddAssetPath(path)) {
721ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path");
722cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
723cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
724cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
725fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
726ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // Capture the shared libraries so that the final resource table can be properly flattened
727ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // with support for shared libraries.
728ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    for (auto& entry : asset_source->GetAssignedPackageIds()) {
729f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
730ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        final_table_.included_packages_[entry.first] = entry.second;
731ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
732ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    }
733ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
734ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->AppendSource(std::move(asset_source));
735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
73736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
738b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski  Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
739cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure the first element is <manifest> with package attribute.
740b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
741b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (manifest_el == nullptr) {
742b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
743b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
74436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
745b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    AppInfo app_info;
746b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
747b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
748b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>");
749b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
750b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
751fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
752b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package");
753b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!package_attr) {
754b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source)
755b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                  << "<manifest> must have a 'package' attribute");
756b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
757b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
758b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    app_info.package = package_attr->value;
759b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
760b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* version_code_attr =
761b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) {
762b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_attr->value);
763b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
764b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
765b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:versionCode '" << version_code_attr->value << "'");
7661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return {};
767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
768b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.version_code = maybe_code.value();
769b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
770cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
771b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* revision_code_attr =
772b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
773b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value);
774b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
775b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
776b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:revisionCode '" << revision_code_attr->value << "'");
777b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        return {};
778cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
779b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.revision_code = maybe_code.value();
780b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
781cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
782b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) {
783b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!split_name_attr->value.empty()) {
784b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        app_info.split_name = split_name_attr->value;
785cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
786b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
787cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
788b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
789b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (xml::Attribute* min_sdk =
790b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski              uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
791d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value);
792cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
793cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
794b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    return app_info;
795cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
798b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski   * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
799cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Postcondition: ResourceTable has only one package left. All others are
800ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * stripped, or there is an error and false is returned.
801cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoExternalPackages() {
803d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
804ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
805ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski             pkg->id.value() != context_->GetPackageId();
806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    };
8071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
808cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
809ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
810ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (is_ext_package_func(package)) {
811cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We have a package that is not related to the one we're building!
812cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& type : package->types) {
813cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (const auto& entry : type->entries) {
814ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
815cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
816ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            for (const auto& config_value : entry->values) {
817cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // Special case the occurrence of an ID that is being generated
818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              // for the 'android' package. This is due to legacy reasons.
819d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              if (ValueCast<Id>(config_value->value.get()) && package->name == "android") {
820d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource())
821d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "generated id '" << res_name
822d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "' for external package '" << package->name
823d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "'");
824cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              } else {
825d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource())
826d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "defined resource '" << res_name
827d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "' for external package '" << package->name
828d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "'");
829cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                error = true;
830cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              }
8311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
832cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
8331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
834cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
835cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
836979ccb2e6f3f1f7f00a448eb440a85daf033dc9eAdam Lesinski
837d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(),
838d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                       is_ext_package_func);
839ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    final_table_.packages.erase(new_end_iter, final_table_.packages.end());
840cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
841cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
842cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
843cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
844cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Returns true if no IDs have been set, false otherwise.
845cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
846ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoIdsSet() {
847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
848cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (const auto& type : package->types) {
849cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (type->id) {
850f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
851f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << StringPrintf("%02x", type->id.value())
852f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << " assigned");
853cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
854cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
855cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
856cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& entry : type->entries) {
857cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (entry->id) {
858ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
859ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(
860f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                DiagMessage() << "entry " << res_name << " has ID "
861f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                              << StringPrintf("%02x", entry->id.value()) << " assigned");
862cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
863cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
86464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        }
865cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
86664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
867cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
868cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
86964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
870ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) {
871ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.output_to_directory) {
872ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out);
873cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
874ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out);
8751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
879cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    BigBuffer buffer(1024);
880c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski    TableFlattener flattener(options_.table_flattener_options, &buffer);
881ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!flattener.Consume(context_, table)) {
88206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
883cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
884cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
8851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
88606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    io::BigBufferInputStream input_stream(&buffer);
887d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc",
888d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        ArchiveEntry::kAlign, writer);
889cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
890cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
89206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table);
893d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer);
894cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
896d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
897418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                     const StringPiece& out_package, const JavaClassGeneratorOptions& java_options,
898418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                     const Maybe<std::string> out_text_symbols_path = {}) {
899ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
900cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
9011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
9021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
903ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
904ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(out_package));
905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
906d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
907d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
908cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
909cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
910ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
911ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "R.java");
912ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
913ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
914cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
915d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
917d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
918cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
919ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski    }
920ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
921418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    std::unique_ptr<std::ofstream> fout_text;
922418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    if (out_text_symbols_path) {
923418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      fout_text =
924418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski          util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
925418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      if (!*fout_text) {
926418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski        context_->GetDiagnostics()->Error(
927418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski            DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
928418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                          << "': " << android::base::SystemErrorCodeToString(errno));
929418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski        return false;
930418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      }
931418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    }
932418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski
933ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context_, table, java_options);
934418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
93506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
936cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
937cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
9381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
939cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
940d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
941d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
9431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
944cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
945cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
9461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
947ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
948ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
949cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
95064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
95164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
952ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<ClassDefinition> manifest_class =
953ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        GenerateManifestClass(context_->GetDiagnostics(), manifest_xml);
95464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
955ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_class) {
956cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Something bad happened, but we already logged it, so exit.
957cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
95864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
95964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
960ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (manifest_class->empty()) {
961cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Empty Manifest class, no need to generate it.
962cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
96464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add any JavaDoc annotations to the generated class.
966ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& annotation : options_.javadoc_annotations) {
967ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string proper_annotation = "@";
968ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      proper_annotation += annotation;
969ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_class->GetCommentBuilder()->AppendComment(proper_annotation);
970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
97164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
972ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& package_utf8 = context_->GetCompilationPackage();
97364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
974ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(package_utf8));
97664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
977ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
978d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
979d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
980cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
98264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
983ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "Manifest.java");
98464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
987d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
988d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
989d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
990cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
991cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
99264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
993d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
994d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
995d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
996d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
997cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
999cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
100164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1002d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
1003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!out) {
1004cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
1005fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1006fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1007ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& out_path = out.value();
1008ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
1009cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
1010d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1011d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed to open '" << out_path
1012d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1013cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1014cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1015a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1016ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::WriteKeepSet(&fout, keep_set);
1017cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
1018d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1019d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
1020d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1021cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1022cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1023cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1024cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1025fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1026ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input,
1027ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                                   std::string* out_error) {
1028cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1029ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, out_error);
1030cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
1032cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1033ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTablePbFromCollection(collection.get());
1034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1035fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1036d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) {
1037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = collection->FindFile("resources.arsc.flat");
1038cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!file) {
1039cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
1040fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1041fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1042ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
1043ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTableFromPb(file->GetSource(), data->data(), data->size(),
1044ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           context_->GetDiagnostics());
1045cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1046fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1047ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeStaticLibrary(const std::string& input, bool override) {
1048ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1049d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
1050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1051fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1052ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
1053cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1054ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
1055cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1056ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
1057cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1059fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1060b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get());
1061cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
1062b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library");
1063cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1064cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1065cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1066f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
1067cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!pkg) {
1068b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
1069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1070cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result;
1073ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.no_static_lib_packages) {
1074cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Merge all resources as if they were in the compilation package. This is
1075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // the old behavior of aapt.
1076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Add the package to the set of --extra-packages so we emit an R.java for
1078ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // each library package.
1079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!pkg->name.empty()) {
1080ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        options_.extra_java_packages.insert(pkg->name);
1081cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1083cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      pkg->name = "";
1084cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (override) {
1085b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get());
1086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1087b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->Merge(Source(input), table.get(), collection.get());
1088cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1089cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1090cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1091cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // This is the proper way to merge libraries, where the package name is
1092ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // preserved and resource names are mangled.
1093d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      result =
1094d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get());
1095cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1097cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1098cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1099cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1105fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeResourceTable(io::IFile* file, bool override) {
1107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1108d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table "
1109d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1111fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
1113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!data) {
1114d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
1115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1117fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<ResourceTable> table =
1119d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics());
1120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
1121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1122fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1123fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1125cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeOverlay(file->GetSource(), table.get());
1127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->Merge(file->GetSource(), table.get());
1129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return result;
1131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
113264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) {
1134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1135d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name
1136d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "' from compiled file "
1137d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1138cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1139a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFileOverlay(*file_desc, file);
1143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFile(*file_desc, file);
1145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1146a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1150a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the exports of this file to the table.
1152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) {
1153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (exported_symbol.name.package.empty()) {
1154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        exported_symbol.name.package = context_->GetCompilationPackage();
1155cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1156a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ResourceNameRef res_name = exported_symbol.name;
11585eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Maybe<ResourceName> mangled_name =
1160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetNameMangler()->MangleName(exported_symbol.name);
1161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (mangled_name) {
1162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        res_name = mangled_name.value();
1163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
116452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
1165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::unique_ptr<Id> id = util::make_unique<Id>();
1166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      id->SetSource(file_desc->source.WithLine(exported_symbol.line));
1167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      bool result = final_table_.AddResourceAllowMangled(
1168d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id),
1169d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics());
1170cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!result) {
1171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1172cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1173cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1174cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load as a ZIP file and merges the files within into the
1179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable.
1180cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If override is true, conflicting resources are allowed to override each
1181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * other, in order of last seen.
1182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * An io::IFileCollection is created from the ZIP file and added to the set of
1184cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * io::IFileCollections that are open.
1185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeArchive(const std::string& input, bool override) {
1187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1188d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
1189fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1190fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
1192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
1194cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
1196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
119836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (auto iter = collection->Iterator(); iter->HasNext();) {
1201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergeFile(iter->Next(), override)) {
1202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1203cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
120536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1208cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
1209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1210cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1211cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load and merge into the master ResourceTable. If override
1213cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1215cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file path ends with .flata, .jar, .jack, or .zip the file is treated
1218cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * as ZIP archive
1219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the files within are merged individually.
1220cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1221cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Otherwise the files is processed on its own.
1222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergePath(const std::string& path, bool override) {
1224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") ||
1225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) {
1226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeArchive(path, override);
1227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(path, ".apk")) {
1228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeStaticLibrary(path, override);
1229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
1230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = file_collection_->InsertFile(path);
1232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return MergeFile(file, override);
1233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a file to load and merge into the master ResourceTable. If override
1237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and
1242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * merged into the
1243cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable. If the file ends with .flat, then it is treated like
1244cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * a compiled file
1245cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the header data is read and merged into the final ResourceTable.
1246cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1247cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * All other file types are ignored. This is because these files could be
1248cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * coming from a zip,
1249cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * where we could have other files like classes.dex.
1250cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeFile(io::IFile* file, bool override) {
1252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const Source& src = file->GetSource();
1253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(src.path, ".arsc.flat")) {
1254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeResourceTable(file, override);
1255cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(src.path, ".flat")) {
1257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Try opening the file and looking for an Export header.
1258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
1259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!data) {
1260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open");
1261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
126336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      CompiledFileInputStream input_stream(data->data(), data->size());
1265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      uint32_t num_files = 0;
1266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!input_stream.ReadLittleEndian32(&num_files)) {
1267d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files");
1268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
127036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (uint32_t i = 0; i < num_files; i++) {
1272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        pb::CompiledFile compiled_file;
1273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadCompiledFile(&compiled_file)) {
1274d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src)
1275d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to read compiled file header");
1276cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
127736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
127836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        uint64_t offset, len;
1280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadDataMetaData(&offset, &len)) {
1281d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data");
1282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
128336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
128436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1285d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb(
1286d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            compiled_file, file->GetSource(), context_->GetDiagnostics());
1287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!resource_file) {
1288cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
128936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
129036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1291d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(),
1292d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                               override)) {
1293cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
129436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
1297d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
12986a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // Since AAPT compiles these file types and appends .flat to them, seeing
12996a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // their raw extensions is a sign that they weren't compiled.
1300d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
1301d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type
1302d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                         << " file passed as argument. Must be "
1303d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                            "compiled first into .flat file.");
13046a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      return false;
130536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski    }
130636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1307cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Ignore non .flat files. This could be classes.dex or something else that
1308cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // happens
1309cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // to be in an archive.
1310cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1311cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1312cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1313b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  bool CopyAssetsDirsToApk(IArchiveWriter* writer) {
1314b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets;
1315b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (const std::string& assets_dir : options_.assets_dirs) {
1316b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      Maybe<std::vector<std::string>> files =
1317b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr);
1318b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (!files) {
1319b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1320b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1321b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1322b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      for (const std::string& file : files.value()) {
1323b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_key = "assets/" + file;
1324b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_path = assets_dir;
1325b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        file::AppendPath(&full_path, file);
1326b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1327b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        auto iter = merged_assets.find(full_key);
1328b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        if (iter == merged_assets.end()) {
1329b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          merged_assets.emplace(std::move(full_key),
1330b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                util::make_unique<io::RegularFile>(Source(std::move(full_path))));
1331b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        } else if (context_->IsVerbose()) {
1332b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource())
1333b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                           << "asset file overrides '" << full_path << "'");
1334b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        }
1335b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1336b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1337b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1338b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (auto& entry : merged_assets) {
1339b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      uint32_t compression_flags = ArchiveEntry::kCompress;
1340b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      std::string extension = file::GetExtension(entry.first).to_string();
1341b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (options_.extensions_to_not_compress.count(extension) > 0) {
1342b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        compression_flags = 0u;
1343b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1344b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1345d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags,
1346d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                 writer)) {
1347b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1348b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1349b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1350b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    return true;
1351b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  }
1352b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1354cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Writes the AndroidManifest, ResourceTable, and all XML files referenced by
1355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the ResourceTable to the IArchiveWriter.
1356cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1357d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
1358d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                ResourceTable* table) {
1359b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    const bool keep_raw_values = context_->GetPackageType() == PackageType::kStaticLib;
1360d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    bool result =
1361d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_);
1362cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1363cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1364cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1365cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ResourceFileFlattenerOptions file_flattener_options;
1367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.keep_raw_values = keep_raw_values;
1368d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
1369d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
1370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_auto_version = options_.no_auto_version;
1371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_version_vectors = options_.no_version_vectors;
13724d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    file_flattener_options.no_version_transitions = options_.no_version_transitions;
1373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
1374ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.update_proguard_spec =
1375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        static_cast<bool>(options_.generate_proguard_rules_path);
1376cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1377ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set);
1378cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_flattener.Flatten(table, writer)) {
1380ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources");
1381cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1384b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTableToPb(table, writer)) {
1386cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1387cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1388cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTable(table, writer)) {
1390ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc");
1391cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1392cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1393cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1394cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
13969ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
1397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int Run(const std::vector<std::string>& input_files) {
1398cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Load the AndroidManifest.xml
1399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> manifest_xml =
1400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LoadXml(options_.manifest_path, context_->GetDiagnostics());
1401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_xml) {
1402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1403cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1405d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    // First extract the Package name without modifying it (via --rename-manifest-package).
1406d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (Maybe<AppInfo> maybe_app_info =
1407d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) {
1408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const AppInfo& app_info = maybe_app_info.value();
1409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetCompilationPackage(app_info.package);
1410cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1411fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ManifestFixer manifest_fixer(options_.manifest_fixer_options);
1413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_fixer.Consume(context_, manifest_xml.get())) {
1414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1415cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1417d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<AppInfo> maybe_app_info =
1418d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics());
1419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_app_info) {
1420cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const AppInfo& app_info = maybe_app_info.value();
1424d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0));
14251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});
1427f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1428f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    // Override the package ID when it is "android".
1429f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (context_->GetCompilationPackage() == "android") {
1430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetPackageId(0x01);
1431f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1432f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      // Verify we're building a regular app.
1433b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() != PackageType::kApp) {
1434f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        context_->GetDiagnostics()->Error(
1435f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            DiagMessage() << "package 'android' can only be built as a regular app");
1436f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        return 1;
1437f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      }
1438cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadSymbolsFromIncludePaths()) {
1441cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1442cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    TableMergerOptions table_merger_options;
1445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    table_merger_options.auto_add_overlay = options_.auto_add_overlay;
1446d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);
14471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage()
1450f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                       << StringPrintf("linking package '%s' using package ID %02x",
1451f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetCompilationPackage().data(),
1452f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetPackageId()));
1453cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1454bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : input_files) {
1456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, false)) {
1457d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input");
1458cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1459cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : options_.overlay_files) {
1463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, true)) {
1464d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays");
1465cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1467cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
146864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!VerifyNoExternalPackages()) {
1470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1471cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1473b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() != PackageType::kStaticLib) {
1474cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      PrivateAttributeMover mover;
1475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!mover.Consume(context_, &final_table_)) {
1476d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes");
1477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
147936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1480cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Assign IDs if we are building a regular app.
1481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      IdAssigner id_assigner(&options_.stable_id_map);
1482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!id_assigner.Consume(context_, &final_table_)) {
1483ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs");
1484cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
148636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1487cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now grab each ID and emit it as a file.
1488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.resource_id_map_path) {
1489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& package : final_table_.packages) {
1490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (auto& type : package->types) {
1491cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            for (auto& entry : type->entries) {
1492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              ResourceName name(package->name, type->type, entry->name);
1493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // The IDs are guaranteed to exist.
1494d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              options_.stable_id_map[std::move(name)] =
1495d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                  ResourceId(package->id.value(), type->id.value(), entry->id.value());
14961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
1497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
149836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
149936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1500d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map,
1501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                    options_.resource_id_map_path.value())) {
1502cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
150336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1505cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Static libs are merged with other apps, and ID collisions are bad, so
1507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // verify that
1508cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // no IDs have been set.
1509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!VerifyNoIdsSet()) {
1510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1513cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the names to mangle based on our source merge earlier.
1515d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(
1516d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()});
1517cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1518cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add our table to the symbol table.
1519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->PrependSource(
1520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::make_unique<ResourceTableSymbolSource>(&final_table_));
1521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
15221e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // Workaround for pre-O runtime that would treat negative resource IDs
15231e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // (any ID with a package ID > 7f) as invalid. Intercept any ID (PPTTEEEE) with PP > 0x7f
15241e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // and type == 'id', and return the ID 0x7fPPEEEE. IDs don't need to be real resources, they
15251e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // are just identifiers.
15261e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (context_->GetMinSdkVersion() < SDK_O && context_->GetPackageType() == PackageType::kApp) {
15271e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      if (context_->IsVerbose()) {
15281e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        context_->GetDiagnostics()->Note(DiagMessage()
15291e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                         << "enabling pre-O feature split ID rewriting");
15301e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      }
15311e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      context_->GetExternalSymbols()->SetDelegate(
15321e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          util::make_unique<FeatureSplitSymbolTableDelegate>(context_));
15331e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
15341e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
1535cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ReferenceLinker linker;
1536ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!linker.Consume(context_, &final_table_)) {
1537d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references");
1538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1539cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1541b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1542ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!options_.products.empty()) {
1543ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1544ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't select products when building static library");
1545cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1546cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1547ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ProductFilter product_filter(options_.products);
1548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!product_filter.Consume(context_, &final_table_)) {
1549ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products");
1550cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1551cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1552cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
155336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1554ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_auto_version) {
1555cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      AutoVersioner versioner;
1556ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!versioner.Consume(context_, &final_table_)) {
1557d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles");
1558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1559cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1560cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
156177788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall
1562b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) {
1563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
1564d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage()
1565d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << "collapsing resource versions for minimum SDK "
1566d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << context_->GetMinSdkVersion());
1567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
156836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      VersionCollapser collapser;
1570ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!collapser.Consume(context_, &final_table_)) {
1571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1572cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1573cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1574355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_resource_deduping) {
1576cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      ResourceDeduper deduper;
1577ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!deduper.Consume(context_, &final_table_)) {
1578ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
1579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1580cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1581cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1582cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1583ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_keep_set;
1584ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_main_dex_keep_set;
1585cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1586b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1587ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.table_splitter_options.config_filter != nullptr ||
1588672384b41e1fc7195424533b7aa6753fb771a6cbPierre Lecesne          !options_.table_splitter_options.preferred_densities.empty()) {
1589ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1590ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't strip resources when building static library");
1591cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1592cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1593d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
1594d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // equal to the minSdk.
1595d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      options_.split_constraints =
1596d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
1597cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1598d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
1599ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!table_splitter.VerifySplitConstraints(context_)) {
1600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1602ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      table_splitter.SplitTable(&final_table_);
1603cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now we need to write out the Split APKs.
1605ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      auto path_iter = options_.split_paths.begin();
1606d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      auto split_constraints_iter = options_.split_constraints.begin();
1607d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) {
1608ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (context_->IsVerbose()) {
1609d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Note(DiagMessage(*path_iter)
1610d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "generating split with configurations '"
1611d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << util::Joiner(split_constraints_iter->configs, ", ")
1612d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "'");
16131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1615d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter);
1616ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!archive_writer) {
1617d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1618cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
16191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1621cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Generate an AndroidManifest.xml for each split.
1622ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<xml::XmlResource> split_manifest =
1623ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            GenerateSplitManifest(app_info, *split_constraints_iter);
16241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1625cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        XmlReferenceLinker linker;
1626ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!linker.Consume(context_, split_manifest.get())) {
1627d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage()
1628d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to create Split AndroidManifest.xml");
1629cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1630467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        }
1631467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
1632d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(),
1633d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                      split_table.get())) {
1634cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1635637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall        }
1636637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall
1637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++path_iter;
1638ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++split_constraints_iter;
1639cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1640cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
16419e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1642cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Start writing the base APK.
1643b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(options_.output_path);
1644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!archive_writer) {
1645b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1646cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1647cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
16489e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1649cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1650cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    {
1651cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // AndroidManifest.xml has no resource name, but the CallSite is built
1652cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // from the name
1653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // (aka, which package the AndroidManifest.xml is coming from).
1654cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // So we give it a package name so it can see local resources.
1655ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_xml->file.name.package = context_->GetCompilationPackage();
1656ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      XmlReferenceLinker manifest_linker;
1658ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (manifest_linker.Consume(context_, manifest_xml.get())) {
1659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_proguard_rules_path &&
1660b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1661b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(), &proguard_keep_set)) {
1662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
16631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1665ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_main_dex_proguard_rules_path &&
1666b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1667b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(),
1668b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       &proguard_main_dex_keep_set, true)) {
1669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
1670e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal        }
1671e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal
1672ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_java_class_path) {
1673ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!WriteManifestJavaFile(manifest_xml.get())) {
1674cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1675cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
16761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1678ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_xml_namespaces) {
1679cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // PackageParser will fail if URIs are removed from
1680cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // AndroidManifest.xml.
1681ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          XmlNamespaceRemover namespace_remover(true /* keepUris */);
1682ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!namespace_remover.Consume(context_, manifest_xml.get())) {
1683cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1684cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
16851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1686cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1687cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
16891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1690fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (error) {
1692b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed processing manifest");
1693cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1694cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1695a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski
1696b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) {
1697b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      return 1;
1698b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1699b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1700b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!CopyAssetsDirsToApk(archive_writer.get())) {
1701cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1703fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1704ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.generate_java_class_path) {
1705b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // The set of packages whose R class to call in the main classes
1706b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // onResourcesLoaded callback.
1707b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      std::vector<std::string> packages_to_callback;
1708b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1709b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions template_options;
1710b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1711b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.javadoc_annotations = options_.javadoc_annotations;
1712fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1713b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() == PackageType::kStaticLib ||
1714b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski          options_.generate_non_final_ids) {
1715b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1716ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
1717ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1718b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() == PackageType::kSharedLib) {
1719b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1720b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
1721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
172264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1723ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const StringPiece actual_package = context_->GetCompilationPackage();
1724ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      StringPiece output_package = context_->GetCompilationPackage();
1725ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.custom_java_package) {
1726cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Override the output java package to the custom one.
1727ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        output_package = options_.custom_java_package.value();
1728cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
17291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1730b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the private symbols if required.
1731ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.private_symbols) {
1732b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(options_.private_symbols.value());
1733b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1734cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we defined a private symbols package, we only emit Public symbols
1735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // to the original package, and private and public symbols to the
1736cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // private package.
1737b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1738b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
1739b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
1740b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski                           options)) {
1741b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski          return 1;
1742b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        }
1743b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
17441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1745b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate all the symbols for all extra packages.
1746b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      for (const std::string& extra_package : options_.extra_java_packages) {
1747b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(extra_package);
1748b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1749b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1750b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1751b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
1752cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1753c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski        }
1754b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
17551e21ff00b005110128245a4b0d13a7513a2d5e0cAdam Lesinski
1756b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the main public R class.
1757b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions options = template_options;
1758b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1759b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Only generate public symbols if we have a private package.
1760b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options_.private_symbols) {
1761b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
1762cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1763c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski
1764b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options.rewrite_callback_options) {
1765b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.rewrite_callback_options.value().packages_to_callback =
1766b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski            std::move(packages_to_callback);
1767cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
176864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1769418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
1770418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                         options_.generate_text_symbols_path)) {
1771b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        return 1;
1772cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1773fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski    }
1774fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1775b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) {
1776cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1777e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski    }
1778e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski
1779ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path,
1780ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           proguard_main_dex_keep_set)) {
1781cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1782cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1783cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
1784cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1785355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1786cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
1787ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkOptions options_;
1788ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkContext* context_;
1789ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceTable final_table_;
1790355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1791ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<TableMerger> table_merger_;
1792355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1793cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A pointer to the FileCollection representing the filesystem (not archives).
1794ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<io::FileCollection> file_collection_;
17956a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski
1796cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of IFileCollections. This is mainly here to keep ownership of the
1797cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // collections.
1798ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<io::IFileCollection>> collections_;
1799bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1800cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of ResourceTables. This is here to retain ownership, so that the
1801ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // SymbolTable can use these.
1802ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<ResourceTable>> static_table_includes_;
1803ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1804ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // The set of shared libraries being used, mapping their assigned package ID to package name.
1805ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::map<size_t, std::string> shared_libs_;
1806cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski};
180736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1808ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Link(const std::vector<StringPiece>& args) {
1809cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkContext context;
1810cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkOptions options;
1811ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_arg_list;
1812ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> extra_java_packages;
1813f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  Maybe<std::string> package_id;
1814113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski  std::vector<std::string> configs;
1815ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> preferred_density;
1816ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> product_list;
1817ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool legacy_x_flag = false;
1818ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool require_localization = false;
1819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool verbose = false;
1820ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool shared_lib = false;
1821ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool static_lib = false;
1822ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> stable_id_file_path;
1823ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_args;
1824cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Flags flags =
1825cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      Flags()
1826d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("-o", "Output path.", &options.output_path)
1827d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("--manifest", "Path to the Android manifest to build.",
1828ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_path)
1829d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths)
1830b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          .OptionalFlagList("-A",
1831b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            "An assets directory to include in the APK. These are unprocessed.",
1832b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            &options.assets_dirs)
1833c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("-R",
1834c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "Compilation unit to link, using `overlay` semantics.\n"
1835c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "The last conflicting resource given takes precedence.",
1836c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &overlay_arg_list)
1837f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          .OptionalFlag("--package-id",
1838f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "Specify the package ID to use for this app. Must be greater or equal to\n"
1839f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "0x7f and can't be used with --static-lib or --shared-lib.",
1840f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        &package_id)
1841d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--java", "Directory in which to generate R.java.",
1842ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_java_class_path)
1843d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--proguard", "Output file for generated Proguard rules.",
1844ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_proguard_rules_path)
1845c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--proguard-main-dex",
1846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Output file for generated Proguard rules for the main dex.",
1847c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.generate_main_dex_proguard_rules_path)
1848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--no-auto-version",
1849d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic style and layout SDK versioning.",
1850ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_auto_version)
1851ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-version-vectors",
1852d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of vector drawables. Use this only\n"
1853d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with vector drawable support library.",
1854ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_version_vectors)
18554d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          .OptionalSwitch("--no-version-transitions",
1856d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of transition resources. Use this only\n"
1857d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with transition support library.",
18584d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki                          &options.no_version_transitions)
1859ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-resource-deduping",
1860cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "Disables automatic deduping of resources with\n"
1861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "identical values across compatible configurations.",
1862ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_resource_deduping)
1863c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalSwitch("--enable-sparse-encoding",
1864c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "Enables encoding sparse entries using a binary search tree.\n"
1865c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "This decreases APK size at the cost of resource retrieval performance.",
1866c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &options.table_flattener_options.use_sparse_entries)
1867d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
1868c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &legacy_x_flag)
1869d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
1870ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &require_localization)
1871113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski          .OptionalFlagList("-c",
1872418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            "Comma separated list of configurations to include. The default\n"
1873418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            "is all configurations.",
1874418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            &configs)
1875c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--preferred-density",
1876c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        "Selects the closest matching density and strips out all others.",
1877c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &preferred_density)
1878c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
1879ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--output-to-dir",
1880d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Outputs the APK contents to a directory specified by -o.",
1881ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.output_to_directory)
1882ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-xml-namespaces",
1883d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Removes XML namespace prefix and URI information from\n"
1884d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "AndroidManifest.xml and XML binaries in res/*.",
1885ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_xml_namespaces)
1886ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--min-sdk-version",
1887d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default minimum SDK version to use for AndroidManifest.xml.",
1888ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.min_sdk_version_default)
1889c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--target-sdk-version",
1890d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default target SDK version to use for AndroidManifest.xml.",
1891c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.target_sdk_version_default)
1892ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-code",
1893d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
1894d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "present.",
1895ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_code_default)
1896ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-name",
1897d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version name to inject into the AndroidManifest.xml if none is present.",
1898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_name_default)
1899d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
1900d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          &shared_lib)
1901d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
1902ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-static-lib-packages",
1903d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Merge all library resources under the app's package.",
1904ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_static_lib_packages)
1905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--non-final-ids",
1906d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Generates R.java without the final modifier. This is implied when\n"
1907d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "--static-lib is specified.",
1908ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.generate_non_final_ids)
1909c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
1910ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &stable_id_file_path)
1911c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--emit-ids",
1912d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Emit a file at the given path with a list of name to ID mappings,\n"
1913d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "suitable for use with --stable-ids.",
1914c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.resource_id_map_path)
1915ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--private-symbols",
1916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Package name to use when generating R.java for private symbols.\n"
1917d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "If not specified, public and private symbols will use the application's\n"
1918d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "package name.",
1919ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.private_symbols)
1920d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
1921ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.custom_java_package)
1922ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--extra-packages",
1923d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Generate the same R.java but with different package names.",
1924ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &extra_java_packages)
1925ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--add-javadoc-annotation",
1926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Adds a JavaDoc annotation to all generated Java classes.",
1927ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.javadoc_annotations)
1928418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski          .OptionalFlag("--output-text-symbols",
1929418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        "Generates a text file containing the resource symbols of the R class in\n"
1930418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        "the specified folder.",
1931418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        &options.generate_text_symbols_path)
1932ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--auto-add-overlay",
1933d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Allows the addition of new resources in overlays without\n"
1934d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "<add-resource> tags.",
1935ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.auto_add_overlay)
1936d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
1937ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.rename_manifest_package)
1938c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--rename-instrumentation-target-package",
1939d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Changes the name of the target package for instrumentation. Most useful\n"
1940d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "when used in conjunction with --rename-manifest-package.",
1941c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.rename_instrumentation_target_package)
1942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-0", "File extensions not to compress.",
1943ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.extensions_to_not_compress)
1944c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("--split",
1945d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Split resources matching a set of configs out to a Split APK.\n"
1946db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski                            "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
1947db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski                            "On Windows, use a semicolon ';' separator instead.",
1948c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &split_args)
1949d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
1950cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1951ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flags.Parse("aapt2 link", args, &std::cerr)) {
1952cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 1;
1953cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1954cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1955d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Expand all argument-files passed into the command line. These start with '@'.
1956ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> arg_list;
1957ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : flags.GetArgs()) {
1958ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1959cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1960cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1961ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &arg_list, &error)) {
1962ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1963cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1964cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1966ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      arg_list.push_back(arg);
1967cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1968cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1970cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Expand all argument-files passed to -R.
1971ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : overlay_arg_list) {
1972ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1973cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1974cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) {
1976ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1977cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1978cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1979cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1980ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      options.overlay_files.push_back(arg);
1981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1984cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (verbose) {
1985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context.SetVerbose(verbose);
1986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1987cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1988f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib && static_lib) {
1989f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.GetDiagnostics()->Error(DiagMessage()
1990f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                    << "only one of --shared-lib and --static-lib can be defined");
1991f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    return 1;
1992f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
1993f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1994f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib) {
1995b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kSharedLib);
1996f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(0x00);
1997f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else if (static_lib) {
1998b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kStaticLib);
1999f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
2000f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else {
2001b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kApp);
2002f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
2003f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
2004f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2005f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (package_id) {
2006b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context.GetPackageType() != PackageType::kApp) {
2007f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
2008f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << "can't specify --package-id when not building a regular app");
2009f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2010f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2011f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2012f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
2013f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (!maybe_package_id_int) {
2014f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
2015f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                    << "' is not a valid integer");
2016f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2017f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2018f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2019f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const uint32_t package_id_int = maybe_package_id_int.value();
2020f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
2021f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
2022f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << StringPrintf(
2023f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski              "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
2024f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2025f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2026f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(static_cast<uint8_t>(package_id_int));
2027f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
2028f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2029cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate the set of extra packages for which to generate R.java.
2030ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (std::string& extra_package : extra_java_packages) {
2031cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // A given package can actually be a colon separated list of packages.
2032ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece package : util::Split(extra_package, ':')) {
2033d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski      options.extra_java_packages.insert(package.to_string());
2034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2035cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2036cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2037ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (product_list) {
2038ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
2039cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (product != "" && product != "default") {
2040d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski        options.products.insert(product.to_string());
2041cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
2042cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2043cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2044cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2045d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<IConfigFilter> filter;
2046f4dacf29cc995fad4aea8e8f25811f9ee4685d91Mihai Nita  if (!configs.empty()) {
2047d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
2048d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (filter == nullptr) {
2049d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      return 1;
2050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2051d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.config_filter = filter.get();
2052cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2053cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2054ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (preferred_density) {
2055d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<uint16_t> density =
2056d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics());
2057d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!density) {
2058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2059cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2060d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.preferred_densities.push_back(density.value());
2061d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
2062cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2063d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Parse the split parameters.
2064d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  for (const std::string& split_arg : split_args) {
2065d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_paths.push_back({});
2066d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_constraints.push_back({});
2067d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
2068d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                             &options.split_constraints.back())) {
2069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2070cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2073b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path) {
2074ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
2075ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                         &options.stable_id_map)) {
2076cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2079cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2080cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate some default no-compress extensions that are already compressed.
2081ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.extensions_to_not_compress.insert(
2082cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
2083cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
2084cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
2085cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
2086cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2087cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Turn off auto versioning for static-libs.
2088b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  if (context.GetPackageType() == PackageType::kStaticLib) {
2089ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_auto_version = true;
2090ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_version_vectors = true;
20914d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    options.no_version_transitions = true;
2092cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2093cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2094cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand cmd(&context, options);
2095ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return cmd.Run(arg_list);
20961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
20971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2098cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
2099