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"
53c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski#include "link/XmlCompatVersioner.h"
54d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/ResourceDeduper.h"
55d48944a745f9ed121e6bde22ef6feb3a44fbec39Adam Lesinski#include "optimize/VersionCollapser.h"
561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/IResourceTableConsumer.h"
571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/SymbolTable.h"
5859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h"
59355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "split/TableSplitter.h"
601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "unflatten/BinaryResourceParser.h"
611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Files.h"
62467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h"
631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
64d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece;
65f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinskiusing android::base::StringPrintf;
665eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct LinkOptions {
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string output_path;
71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string manifest_path;
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> include_paths;
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_files;
74b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  std::vector<std::string> assets_dirs;
75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool output_to_directory = false;
76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool auto_add_overlay = false;
77cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Java/Proguard options.
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_java_class_path;
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> custom_java_package;
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::set<std::string> extra_java_packages;
82418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski  Maybe<std::string> generate_text_symbols_path;
83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_proguard_rules_path;
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> generate_main_dex_proguard_rules_path;
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool generate_non_final_ids = false;
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> javadoc_annotations;
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> private_symbols;
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Optimizations/features.
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
924d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_resource_deduping = false;
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Static lib options.
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_static_lib_packages = false;
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // AndroidManifest.xml massaging options.
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ManifestFixerOptions manifest_fixer_options;
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // Products to use/filter on.
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unordered_set<std::string> products;
106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
107c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  // Flattening options.
108c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski  TableFlattenerOptions table_flattener_options;
109c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski
110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Split APK options.
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  TableSplitterOptions table_splitter_options;
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<SplitConstraints> split_constraints;
113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_paths;
114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Stable ID options.
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_map<ResourceName, ResourceId> stable_id_map;
117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> resource_id_map_path;
1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
12064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass LinkContext : public IAaptContext {
121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
122820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warrington  LinkContext(IDiagnostics* diagnostics)
123820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warrington      : diagnostics_(diagnostics), name_mangler_({}), symbols_(&name_mangler_) {
124d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
126b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType GetPackageType() override {
127b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    return package_type_;
128b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
129b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski
130b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  void SetPackageType(PackageType type) {
131b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    package_type_ = type;
132b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
133b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski
134d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  IDiagnostics* GetDiagnostics() override {
135820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warrington    return diagnostics_;
136d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
138d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  NameMangler* GetNameMangler() override {
139d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &name_mangler_;
140d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void SetNameManglerPolicy(const NameManglerPolicy& policy) {
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    name_mangler_ = NameMangler(policy);
144cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
14564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const std::string& GetCompilationPackage() override {
147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return compilation_package_;
148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void SetCompilationPackage(const StringPiece& package_name) {
151d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    compilation_package_ = package_name.to_string();
152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
15364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
154d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  uint8_t GetPackageId() override {
155d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return package_id_;
156d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
158d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetPackageId(uint8_t id) {
159d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    package_id_ = id;
160d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
16164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
162d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  SymbolTable* GetExternalSymbols() override {
163d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &symbols_;
164d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
165355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
166d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool IsVerbose() override {
167d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return verbose_;
168d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
16964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
170d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetVerbose(bool val) {
171d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    verbose_ = val;
172d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
17364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
174d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  int GetMinSdkVersion() override {
175d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return min_sdk_version_;
176d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
177fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
178d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetMinSdkVersion(int minSdk) {
179d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    min_sdk_version_ = minSdk;
180d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
181fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(LinkContext);
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
185b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType package_type_ = PackageType::kApp;
186820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warrington  IDiagnostics* diagnostics_;
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  NameMangler name_mangler_;
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string compilation_package_;
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint8_t package_id_ = 0x0;
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SymbolTable symbols_;
191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool verbose_ = false;
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int min_sdk_version_ = 0;
1931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1951e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// A custom delegate that generates compatible pre-O IDs for use with feature splits.
1961e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// Feature splits use package IDs > 7f, which in Java (since Java doesn't have unsigned ints)
1971e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// is interpreted as a negative number. Some verification was wrongly assuming negative values
1981e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// were invalid.
1991e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski//
2001e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE,
2011e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such
2021e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski// an overlap exists.
2031e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinskiclass FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
2041e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski public:
2051e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
2061e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  }
2071e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2081e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  virtual ~FeatureSplitSymbolTableDelegate() = default;
2091e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2101e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
2111e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      const ResourceName& name,
2121e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      const std::vector<std::unique_ptr<ISymbolSource>>& sources) override {
2131e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    std::unique_ptr<SymbolTable::Symbol> symbol =
2141e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        DefaultSymbolTableDelegate::FindByName(name, sources);
2151e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (symbol == nullptr) {
2161e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      return {};
2171e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
2181e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2191e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // Check to see if this is an 'id' with the target package.
2201e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (name.type == ResourceType::kId && symbol->id) {
2211e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      ResourceId* id = &symbol->id.value();
2221e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      if (id->package_id() > kAppPackageId) {
2231e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        // Rewrite the resource ID to be compatible pre-O.
2241e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        ResourceId rewritten_id(kAppPackageId, id->package_id(), id->entry_id());
2251e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2261e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        // Check that this doesn't overlap another resource.
2271e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        if (DefaultSymbolTableDelegate::FindById(rewritten_id, sources) != nullptr) {
2281e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          // The ID overlaps, so log a message (since this is a weird failure) and fail.
2291e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "Failed to rewrite " << name
2301e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                                          << " for pre-O feature split support");
2311e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          return {};
2321e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        }
2331e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2341e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        if (context_->IsVerbose()) {
2351e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          context_->GetDiagnostics()->Note(DiagMessage() << "rewriting " << name << " (" << *id
2361e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                                         << ") -> (" << rewritten_id << ")");
2371e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        }
2381e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2391e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        *id = rewritten_id;
2401e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      }
2411e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
2421e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    return symbol;
2431e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  }
2441e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2451e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski private:
2461e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  DISALLOW_COPY_AND_ASSIGN(FeatureSplitSymbolTableDelegate);
2471e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
2481e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski  IAaptContext* context_;
2491e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski};
2501e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
251c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistatic bool FlattenXml(IAaptContext* context, xml::XmlResource* xml_res, const StringPiece& path,
252c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                       bool keep_raw_values, IArchiveWriter* writer) {
253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  BigBuffer buffer(1024);
254cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  XmlFlattenerOptions options = {};
255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.keep_raw_values = keep_raw_values;
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()) {
262c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
263c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                      << (keep_raw_values ? "true" : "false")
264c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                      << ")");
265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
26659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
26706460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  io::BigBufferInputStream input_stream(&buffer);
268d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
269d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                      ArchiveEntry::kCompress, writer);
270355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
27159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
272d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data,
273d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      size_t len, IDiagnostics* diag) {
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  pb::ResourceTable pb_table;
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!pb_table.ParseFromArray(data, len)) {
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(source) << "invalid compiled table");
277cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
278cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
28006460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski  std::unique_ptr<ResourceTable> table = DeserializeTableFromPb(pb_table, source, diag);
281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!table) {
282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
283cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
284cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return table;
285355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
2861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
287355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/**
288355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Inflates an XML file from the source path.
289355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */
290d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
291cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::ifstream fin(path, std::ifstream::binary);
292cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fin) {
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << strerror(errno));
294cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return {};
295cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return xml::Inflate(&fin, diag, Source(path));
297355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
2981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
299355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistruct ResourceFileFlattenerOptions {
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_auto_version = false;
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_version_vectors = false;
3024d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki  bool no_version_transitions = false;
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool no_xml_namespaces = false;
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool keep_raw_values = false;
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool do_not_compress_anything = false;
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool update_proguard_spec = false;
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unordered_set<std::string> extensions_to_not_compress;
308355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
309355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
310c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski// A sampling of public framework resource IDs.
311c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistruct R {
312c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  struct attr {
313c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    enum : uint32_t {
314c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingLeft = 0x010100d6u,
315c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingRight = 0x010100d8u,
316c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingHorizontal = 0x0101053du,
317c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
318c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingTop = 0x010100d7u,
319c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingBottom = 0x010100d9u,
320c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      paddingVertical = 0x0101053eu,
321c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
322c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginLeft = 0x010100f7u,
323c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginRight = 0x010100f9u,
324c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginHorizontal = 0x0101053bu,
325c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
326c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginTop = 0x010100f8u,
327c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginBottom = 0x010100fau,
328c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      layout_marginVertical = 0x0101053cu,
329c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
330c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  };
331c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski};
332c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
333355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass ResourceFileFlattener {
334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
335d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context,
336c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                        proguard::KeepSet* keep_set);
3371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer);
339355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
340cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
341cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  struct FileOperation {
342cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ConfigDescription config;
3435eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
344cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The entry this file came from.
345c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    ResourceEntry* entry;
3465eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
347cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The file to copy as-is.
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file_to_copy;
3495eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
350cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The XML to process and flatten.
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> xml_to_flatten;
3525eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
353cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // The destination to write this file to.
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string dst_path;
355cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  };
356355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  uint32_t GetCompressionFlags(const StringPiece& str);
358355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
359c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<std::unique_ptr<xml::XmlResource>> LinkAndVersionXmlFile(ResourceTable* table,
360c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                                       FileOperation* file_op);
361355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceFileFlattenerOptions options_;
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  IAaptContext* context_;
364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  proguard::KeepSet* keep_set_;
365c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner::Rules rules_;
366355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski};
367355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
368c744ae8aca97edfb2422598ea620e8219449fa9bAdam LesinskiResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
369c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                             IAaptContext* context, proguard::KeepSet* keep_set)
370c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    : options_(options), context_(context), keep_set_(keep_set) {
371c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  SymbolTable* symm = context_->GetExternalSymbols();
372c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
373c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  // Build up the rules for degrading newer attributes to older ones.
374c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  // NOTE(adamlesinski): These rules are hardcoded right now, but they should be
375c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  // generated from the attribute definitions themselves (b/62028956).
376c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingHorizontal)) {
377c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    std::vector<ReplacementAttr> replacements{
378c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"paddingLeft", R::attr::paddingLeft,
379c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
380c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"paddingRight", R::attr::paddingRight,
381c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
382c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
383c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    rules_[R::attr::paddingHorizontal] =
384c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        util::make_unique<DegradeToManyRule>(std::move(replacements));
385c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
386c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
387c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingVertical)) {
388c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    std::vector<ReplacementAttr> replacements{
389c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"paddingTop", R::attr::paddingTop,
390c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
391c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"paddingBottom", R::attr::paddingBottom,
392c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
393c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
394c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    rules_[R::attr::paddingVertical] =
395c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        util::make_unique<DegradeToManyRule>(std::move(replacements));
396c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
397c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
398c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginHorizontal)) {
399c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    std::vector<ReplacementAttr> replacements{
400c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"layout_marginLeft", R::attr::layout_marginLeft,
401c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
402c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"layout_marginRight", R::attr::layout_marginRight,
403c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
404c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
405c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    rules_[R::attr::layout_marginHorizontal] =
406c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        util::make_unique<DegradeToManyRule>(std::move(replacements));
407c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
408c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
409c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginVertical)) {
410c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    std::vector<ReplacementAttr> replacements{
411c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"layout_marginTop", R::attr::layout_marginTop,
412c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
413c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        {"layout_marginBottom", R::attr::layout_marginBottom,
414c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski         Attribute(false, android::ResTable_map::TYPE_DIMENSION)},
415c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    };
416c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    rules_[R::attr::layout_marginVertical] =
417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        util::make_unique<DegradeToManyRule>(std::move(replacements));
418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiuint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
422ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.do_not_compress_anything) {
423cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
424cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
425355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& extension : options_.extensions_to_not_compress) {
427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(str, extension)) {
428cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 0;
429355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
430cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
431cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return ArchiveEntry::kCompress;
432355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
433355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
4344d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Arakistatic bool IsTransitionElement(const std::string& name) {
435d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
436d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeImageTransform" || name == "changeTransform" ||
437d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
438d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "changeScroll" || name == "transitionSet" || name == "transition" ||
439d0f492db038c6210c1138865d816bfb134376538Adam Lesinski         name == "transitionManager";
4404d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki}
4414d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki
442c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistatic bool IsVectorElement(const std::string& name) {
44341ea44f63d78b03a7c323639f3b80364b65f5a13Adam Lesinski  return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
44441ea44f63d78b03a7c323639f3b80364b65f5a13Adam Lesinski         name == "objectAnimator";
445c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
446c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
447c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskitemplate <typename T>
448c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::vector<T> make_singleton_vec(T&& val) {
449c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  std::vector<T> vec;
450c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  vec.emplace_back(std::forward<T>(val));
451c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return vec;
452c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
453c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
454c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile(
455c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    ResourceTable* table, FileOperation* file_op) {
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  xml::XmlResource* doc = file_op->xml_to_flatten.get();
457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  const Source& src = doc->file.source;
458355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (context_->IsVerbose()) {
460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path);
461cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
462355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XmlReferenceLinker xml_linker;
464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!xml_linker.Consume(context_, doc)) {
465c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    return {};
466cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
467355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
468d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) {
469c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    return {};
470cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
471cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (options_.no_xml_namespaces) {
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    XmlNamespaceRemover namespace_remover;
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!namespace_remover.Consume(context_, doc)) {
475c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return {};
476355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
478355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
479c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (options_.no_auto_version) {
480c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    return make_singleton_vec(std::move(file_op->xml_to_flatten));
481c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
482cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
483c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  if (options_.no_version_vectors || options_.no_version_transitions) {
484c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    // Skip this if it is a vector or animated-vector.
485c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    xml::Element* el = xml::FindRootElement(doc);
486c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (el && el->namespace_uri.empty()) {
487c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      if ((options_.no_version_vectors && IsVectorElement(el->name)) ||
488c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          (options_.no_version_transitions && IsTransitionElement(el->name))) {
489c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        return make_singleton_vec(std::move(file_op->xml_to_flatten));
490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
49152364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski    }
492cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
493c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
494c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const ConfigDescription& config = file_op->config;
495c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  ResourceEntry* entry = file_op->entry;
496c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
497c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  XmlCompatVersioner xml_compat_versioner(&rules_);
498c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  const util::Range<ApiVersion> api_range{config.sdkVersion,
499c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                          FindNextApiVersionForConfig(entry, config)};
500c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return xml_compat_versioner.Process(context_, doc, api_range);
501355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
50252364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
503d0f492db038c6210c1138865d816bfb134376538Adam Lesinskibool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool error = false;
505d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
507cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  for (auto& pkg : table->packages) {
508cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (auto& type : pkg->types) {
509c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      // Sort by config and name, so that we get better locality in the zip file.
510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      config_sorted_files.clear();
511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::queue<FileOperation> file_operations;
512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
513cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Populate the queue with all files in the ResourceTable.
514cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (auto& entry : type->entries) {
515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& config_value : entry->values) {
516c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // WARNING! Do not insert or remove any resources while executing in this scope. It will
517c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // corrupt the iteration order.
518c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!file_ref) {
521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            continue;
522cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
523355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          io::IFile* file = file_ref->file;
525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (!file) {
526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource())
527cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                              << "file not found");
528cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
529cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
530355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
531ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          FileOperation file_op;
532ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.entry = entry.get();
533ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.dst_path = *file_ref->path;
534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          file_op.config = config_value->config;
535c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          file_op.file_to_copy = file;
536355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          const StringPiece src_path = file->GetSource().path;
538cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (type->type != ResourceType::kRaw &&
539d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) {
540ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            std::unique_ptr<io::IData> data = file->OpenAsData();
541cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            if (!data) {
542ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
543cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                                << "failed to open file");
544cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
545355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski            }
546355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
547d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(),
548d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  context_->GetDiagnostics(), file->GetSource());
549355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            if (!file_op.xml_to_flatten) {
551cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              return false;
552a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski            }
553cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
554ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.config = config_value->config;
555ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            file_op.xml_to_flatten->file.source = file_ref->GetSource();
556d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
559c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // NOTE(adamlesinski): Explicitly construct a StringPiece here, or
560c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // else we end up copying the string in the std::make_pair() method,
561c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // then creating a StringPiece from the copy, which would cause us
562c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          // to end up referencing garbage in the map.
563c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          const StringPiece entry_name(entry->name);
564c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          config_sorted_files[std::make_pair(config_value->config, entry_name)] =
565c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              std::move(file_op);
566cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
567cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
568cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now flatten the sorted values.
570ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (auto& map_entry : config_sorted_files) {
571ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const ConfigDescription& config = map_entry.first.first;
572c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski        FileOperation& file_op = map_entry.second;
573ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
574ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (file_op.xml_to_flatten) {
575c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
576c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              LinkAndVersionXmlFile(table, &file_op);
577c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          for (std::unique_ptr<xml::XmlResource>& doc : versioned_docs) {
578c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            std::string dst_path = file_op.dst_path;
579c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            if (doc->file.config != file_op.config) {
580c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              // Only add the new versioned configurations.
581c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              if (context_->IsVerbose()) {
582c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                context_->GetDiagnostics()->Note(DiagMessage(doc->file.source)
583c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                 << "auto-versioning resource from config '"
584c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                 << config << "' -> '" << doc->file.config << "'");
585c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              }
586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
587c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              dst_path =
588c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                  ResourceUtils::BuildResourceFileName(doc->file, context_->GetNameMangler());
589c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              bool result = table->AddFileReferenceAllowMangled(doc->file.name, doc->file.config,
590c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                                doc->file.source, dst_path, nullptr,
591c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                                                context_->GetDiagnostics());
592c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              if (!result) {
593c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                return false;
594c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski              }
595c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            }
596c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski            error |= !FlattenXml(context_, doc.get(), dst_path, options_.keep_raw_values,
597c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                 archive_writer);
598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
599cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        } else {
600c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski          error |= !io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
601c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski                                          GetCompressionFlags(file_op.dst_path), archive_writer);
6021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
603cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
604355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
605cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
606cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return !error;
607355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}
608a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
609d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool WriteStableIdMapToPath(IDiagnostics* diag,
610d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::unordered_map<ResourceName, ResourceId>& id_map,
611d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                   const std::string& id_map_path) {
612ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::ofstream fout(id_map_path, std::ofstream::binary);
613cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
614ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(id_map_path) << strerror(errno));
615cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
617bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
618ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const auto& entry : id_map) {
619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceName& name = entry.first;
620cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    const ResourceId& id = entry.second;
621cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    fout << name << " = " << id << "\n";
622cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
623bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
624cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!fout) {
625d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
626d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << android::base::SystemErrorCodeToString(errno));
627cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
628cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
629bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
630cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
631bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
632bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
633d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
634d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            std::unordered_map<ResourceName, ResourceId>* out_id_map) {
635cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string content;
6362354b568379fe31ba4e774f7a92d4c685a60a2abAdam Lesinski  if (!android::base::ReadFileToString(path, &content, true /*follow_symlinks*/)) {
637ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    diag->Error(DiagMessage(path) << "failed reading stable ID file");
638cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return false;
639cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
640bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
641ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  out_id_map->clear();
642ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  size_t line_no = 0;
643ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (StringPiece line : util::Tokenize(content, '\n')) {
644ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line_no++;
645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    line = util::TrimWhitespace(line);
646cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (line.empty()) {
647cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      continue;
648cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
649bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
650cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    auto iter = std::find(line.begin(), line.end(), '=');
651cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (iter == line.end()) {
652ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "missing '='");
653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
654cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
655bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
656cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ResourceNameRef name;
657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    StringPiece res_name_str =
658ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
659ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!ResourceUtils::ParseResourceName(res_name_str, &name)) {
660d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str
661d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
662cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
663cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
664bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
665ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1;
666ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const size_t res_id_str_len = line.size() - res_id_start_idx;
667d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));
668bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
669ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str);
670ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_id) {
671d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str
672d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "'");
673cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
674bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski    }
675cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
676ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    (*out_id_map)[name.ToResourceName()] = maybe_id.value();
677cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
678cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return true;
679bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski}
680bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
681355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass LinkCommand {
682cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
683cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand(LinkContext* context, const LinkOptions& options)
684ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      : options_(options),
685ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_(context),
686ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        final_table_(),
687d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        file_collection_(util::make_unique<io::FileCollection>()) {
688d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
689cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
690cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
691cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Creates a SymbolTable that loads symbols from the various APKs and caches
692ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the results for faster lookup.
693cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
694ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool LoadSymbolsFromIncludePaths() {
695ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<AssetManagerSymbolSource> asset_source =
696cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        util::make_unique<AssetManagerSymbolSource>();
697ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& path : options_.include_paths) {
698ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
699d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path");
700cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
701cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // First try to load the file as a static lib.
703ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string error_str;
704ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      std::unique_ptr<ResourceTable> include_static = LoadStaticLibrary(path, &error_str);
705ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      if (include_static) {
706b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski        if (context_->GetPackageType() != PackageType::kStaticLib) {
707ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // Can't include static libraries when not building a static library (they have no IDs
708ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski          // assigned).
709ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetDiagnostics()->Error(
710ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski              DiagMessage(path) << "can't include static library when not building a static lib");
711cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
712cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
71364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
714cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we are using --no-static-lib-packages, we need to rename the
715f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        // package of this table to our compilation package.
716ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_static_lib_packages) {
717f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // Since package names can differ, and multiple packages can exist in a ResourceTable,
718f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // we place the requirement that all static libraries are built with the package
719f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          // ID 0x7f. So if one is not found, this is an error.
720f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          if (ResourceTablePackage* pkg = include_static->FindPackageById(kAppPackageId)) {
721ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            pkg->name = context_->GetCompilationPackage();
722f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          } else {
723f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            context_->GetDiagnostics()->Error(DiagMessage(path)
724f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                              << "no package with ID 0x7f found in static library");
725f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            return false;
726cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
727355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski        }
72864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
729ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetExternalSymbols()->AppendSource(
730ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski            util::make_unique<ResourceTableSymbolSource>(include_static.get()));
7311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
732ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        static_table_includes_.push_back(std::move(include_static));
733fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
734ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (!error_str.empty()) {
735cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We had an error with reading, so fail.
736ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << error_str);
737cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
738cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
739fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
740ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!asset_source->AddAssetPath(path)) {
741ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(path) << "failed to load include path");
742cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
743cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
744cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
745fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
746ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // Capture the shared libraries so that the final resource table can be properly flattened
747ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    // with support for shared libraries.
748ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    for (auto& entry : asset_source->GetAssignedPackageIds()) {
749f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
750ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        final_table_.included_packages_[entry.first] = entry.second;
751ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
752ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    }
753ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
754ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->AppendSource(std::move(asset_source));
755cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
756cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
75736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
758b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski  Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
759cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure the first element is <manifest> with package attribute.
760b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
761b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (manifest_el == nullptr) {
762b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
763b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
76436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
765b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    AppInfo app_info;
766b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
767b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
768b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>");
769b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
770b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
771fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
772b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package");
773b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (!package_attr) {
774b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      diag->Error(DiagMessage(xml_res->file.source)
775b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                  << "<manifest> must have a 'package' attribute");
776b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      return {};
777b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
778b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    app_info.package = package_attr->value;
779b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski
780b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* version_code_attr =
781b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) {
782b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_attr->value);
783b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
784b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
785b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:versionCode '" << version_code_attr->value << "'");
7861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return {};
787cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
788b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.version_code = maybe_code.value();
789b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
790cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
791b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* revision_code_attr =
792b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski            manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
793b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(revision_code_attr->value);
794b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!maybe_code) {
795b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
796b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski                    << "invalid android:revisionCode '" << revision_code_attr->value << "'");
797b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        return {};
798cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
799b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      app_info.revision_code = maybe_code.value();
800b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
801cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
802b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) {
803b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (!split_name_attr->value.empty()) {
804b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski        app_info.split_name = split_name_attr->value;
805cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
806b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    }
807cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
808b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
809b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski      if (xml::Attribute* min_sdk =
810b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski              uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
811d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value);
812cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
813cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
814b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski    return app_info;
815cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
816cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
817cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
818b0c47ef8779e445865e63355ab66265461e1f2a3Adam Lesinski   * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Postcondition: ResourceTable has only one package left. All others are
820ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * stripped, or there is an error and false is returned.
821cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
822ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoExternalPackages() {
823d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
824ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
825ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski             pkg->id.value() != context_->GetPackageId();
826cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    };
8271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
828cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
829ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
830ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (is_ext_package_func(package)) {
831cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // We have a package that is not related to the one we're building!
832cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& type : package->types) {
833cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (const auto& entry : type->entries) {
834ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
835cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
836ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            for (const auto& config_value : entry->values) {
837cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // Special case the occurrence of an ID that is being generated
838ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              // for the 'android' package. This is due to legacy reasons.
839d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              if (ValueCast<Id>(config_value->value.get()) && package->name == "android") {
840d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource())
841d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "generated id '" << res_name
842d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "' for external package '" << package->name
843d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                 << "'");
844cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              } else {
845d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource())
846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "defined resource '" << res_name
847d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "' for external package '" << package->name
848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                  << "'");
849cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                error = true;
850cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              }
8511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
852cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
8531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
854cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
855cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
856979ccb2e6f3f1f7f00a448eb440a85daf033dc9eAdam Lesinski
857d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(),
858d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                       is_ext_package_func);
859ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    final_table_.packages.erase(new_end_iter, final_table_.packages.end());
860cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
861cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
862cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
863cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
864cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Returns true if no IDs have been set, false otherwise.
865cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
866ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool VerifyNoIdsSet() {
867ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& package : final_table_.packages) {
868cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      for (const auto& type : package->types) {
869cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (type->id) {
870f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "type " << type->type << " has ID "
871f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << StringPrintf("%02x", type->id.value())
872f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                          << " assigned");
873cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
874cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
875cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
876cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        for (const auto& entry : type->entries) {
877cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          if (entry->id) {
878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            ResourceNameRef res_name(package->name, type->type, entry->name);
879ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            context_->GetDiagnostics()->Error(
880f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                DiagMessage() << "entry " << res_name << " has ID "
881f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                              << StringPrintf("%02x", entry->id.value()) << " assigned");
882cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            return false;
883cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
88464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        }
885cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
88664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
887cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
888cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
88964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
890ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) {
891ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.output_to_directory) {
892ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out);
893cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
894ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out);
8951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
896cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
8971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
899cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    BigBuffer buffer(1024);
900c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski    TableFlattener flattener(options_.table_flattener_options, &buffer);
901ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!flattener.Consume(context_, table)) {
90206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
903cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
904cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
9051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
90606460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    io::BigBufferInputStream input_stream(&buffer);
907d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc",
908d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        ArchiveEntry::kAlign, writer);
909cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
910cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
911ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
91206460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski    std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table);
913d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer);
914cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
9151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
917418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                     const StringPiece& out_package, const JavaClassGeneratorOptions& java_options,
918418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                     const Maybe<std::string> out_text_symbols_path = {}) {
919ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
920cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
9211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
9221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
923ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
924ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(out_package));
925ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
927d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
928cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
929cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
930ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
931ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "R.java");
932ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
933ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
934cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
935d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
936d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
937d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
938cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
939ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski    }
940ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
941418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    std::unique_ptr<std::ofstream> fout_text;
942418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    if (out_text_symbols_path) {
943418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      fout_text =
944418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski          util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
945418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      if (!*fout_text) {
946418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski        context_->GetDiagnostics()->Error(
947418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski            DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
948418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                          << "': " << android::base::SystemErrorCodeToString(errno));
949418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski        return false;
950418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      }
951418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    }
952418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski
953ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    JavaClassGenerator generator(context_, table, java_options);
954418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski    if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
95506460ef0d7072114ea3280e1650f77f55e7223f4Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
956cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
957cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
9581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
959cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
960d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
961d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
962d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
9631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
964cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
965cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
9661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
967ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
968ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.generate_java_class_path) {
969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
97064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
97164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
972ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<ClassDefinition> manifest_class =
973ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        GenerateManifestClass(context_->GetDiagnostics(), manifest_xml);
97464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_class) {
976cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Something bad happened, but we already logged it, so exit.
977cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
97864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
97964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
980ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (manifest_class->empty()) {
981cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Empty Manifest class, no need to generate it.
982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
98464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
985cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add any JavaDoc annotations to the generated class.
986ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& annotation : options_.javadoc_annotations) {
987ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::string proper_annotation = "@";
988ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      proper_annotation += annotation;
989ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_class->GetCommentBuilder()->AppendComment(proper_annotation);
990cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
99164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
992ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& package_utf8 = context_->GetCompilationPackage();
99364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
994ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string out_path = options_.generate_java_class_path.value();
995ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, file::PackageToPath(package_utf8));
99664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
997ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file::mkdirs(out_path)) {
998d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
999d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                      << "'");
1000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1001cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
100264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1003ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file::AppendPath(&out_path, "Manifest.java");
100464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1005ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
1006cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
1007d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1008d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
1009d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1010cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1011cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
101264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1013d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
1014d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1015d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
1016d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1017cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1018cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1019cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1020cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
102164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1022d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
1023cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!out) {
1024cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
1025fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1026fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1027ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const std::string& out_path = out.value();
1028ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::ofstream fout(out_path, std::ofstream::binary);
1029cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
1030d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1031d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed to open '" << out_path
1032d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1033cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1034cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1035a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1036ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::WriteKeepSet(&fout, keep_set);
1037cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!fout) {
1038d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage()
1039d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "failed writing to '" << out_path
1040d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                        << "': " << android::base::SystemErrorCodeToString(errno));
1041cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1042cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1043cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1044cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1045fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1046ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input,
1047ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                                   std::string* out_error) {
1048cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1049ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, out_error);
1050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1051cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
1052cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1053ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTablePbFromCollection(collection.get());
1054cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1055fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1056d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) {
1057ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = collection->FindFile("resources.arsc.flat");
1058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!file) {
1059cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return {};
1060fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1061fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1062ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
1063ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return LoadTableFromPb(file->GetSource(), data->data(), data->size(),
1064ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           context_->GetDiagnostics());
1065cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1066fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1067ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeStaticLibrary(const std::string& input, bool override) {
1068ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1069d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
1070cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1071fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1072ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
1073cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1074ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
1075cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1076ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
1077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1079fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1080b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    std::unique_ptr<ResourceTable> table = LoadTablePbFromCollection(collection.get());
1081cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
1082b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library");
1083cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1084cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1085cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1086f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
1087cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!pkg) {
1088b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << "static library has no package");
1089cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1090cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1091cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1092cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result;
1093ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.no_static_lib_packages) {
1094cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Merge all resources as if they were in the compilation package. This is
1095ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // the old behavior of aapt.
1096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1097cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Add the package to the set of --extra-packages so we emit an R.java for
1098ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // each library package.
1099cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!pkg->name.empty()) {
1100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        options_.extra_java_packages.insert(pkg->name);
1101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      pkg->name = "";
1104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (override) {
1105b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->MergeOverlay(Source(input), table.get(), collection.get());
1106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1107b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        result = table_merger_->Merge(Source(input), table.get(), collection.get());
1108cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1110cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // This is the proper way to merge libraries, where the package name is
1112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      // preserved and resource names are mangled.
1113d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      result =
1114d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get());
1115cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1116cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1121cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1123cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1125fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeResourceTable(io::IFile* file, bool override) {
1127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1128d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table "
1129d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1131fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
1133cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!data) {
1134d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
1135cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1136cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1137fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1138cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<ResourceTable> table =
1139d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics());
1140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
1141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1142fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1143fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1144cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeOverlay(file->GetSource(), table.get());
1147cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->Merge(file->GetSource(), table.get());
1149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return result;
1151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
115264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1153d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) {
1154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1155d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name
1156d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << "' from compiled file "
1157d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                     << file->GetSource());
1158cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1159a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1160cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool result = false;
1161cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (override) {
1162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFileOverlay(*file_desc, file);
1163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      result = table_merger_->MergeFile(*file_desc, file);
1165cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1166a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1170a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1171cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the exports of this file to the table.
1172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) {
1173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (exported_symbol.name.package.empty()) {
1174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        exported_symbol.name.package = context_->GetCompilationPackage();
1175cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1176a40e972fdaa68fc486ff90a319195515819068b2Adam Lesinski
1177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ResourceNameRef res_name = exported_symbol.name;
11785eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Maybe<ResourceName> mangled_name =
1180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context_->GetNameMangler()->MangleName(exported_symbol.name);
1181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (mangled_name) {
1182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        res_name = mangled_name.value();
1183cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
118452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski
1185cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::unique_ptr<Id> id = util::make_unique<Id>();
1186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      id->SetSource(file_desc->source.WithLine(exported_symbol.line));
1187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      bool result = final_table_.AddResourceAllowMangled(
1188d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id),
1189d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics());
1190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!result) {
1191cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1193cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1194cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1195cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1198cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load as a ZIP file and merges the files within into the
1199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable.
1200cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If override is true, conflicting resources are allowed to override each
1201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * other, in order of last seen.
1202cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1203cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * An io::IFileCollection is created from the ZIP file and added to the set of
1204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * io::IFileCollections that are open.
1205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeArchive(const std::string& input, bool override) {
1207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1208d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
1209fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski    }
1210fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::string error_str;
1212cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::unique_ptr<io::ZipFileCollection> collection =
1213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        io::ZipFileCollection::Create(input, &error_str);
1214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!collection) {
1215ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
1216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
121836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (auto iter = collection->Iterator(); iter->HasNext();) {
1221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergeFile(iter->Next(), override)) {
1222cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1223cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
122536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Make sure to move the collection into the set of IFileCollections.
1227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    collections_.push_back(std::move(collection));
1228cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return !error;
1229cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1231cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1232cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a path to load and merge into the master ResourceTable. If override
1233cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1234cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1235cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1236cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1237cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file path ends with .flata, .jar, .jack, or .zip the file is treated
1238cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * as ZIP archive
1239cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the files within are merged individually.
1240cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1241cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Otherwise the files is processed on its own.
1242cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergePath(const std::string& path, bool override) {
1244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") ||
1245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) {
1246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeArchive(path, override);
1247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(path, ".apk")) {
1248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeStaticLibrary(path, override);
1249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
1250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = file_collection_->InsertFile(path);
1252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return MergeFile(file, override);
1253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1254cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1255cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1256cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Takes a file to load and merge into the master ResourceTable. If override
1257cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * is true,
1258cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * conflicting resources are allowed to override each other, in order of last
1259cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * seen.
1260cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1261cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and
1262cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * merged into the
1263cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * master ResourceTable. If the file ends with .flat, then it is treated like
1264cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * a compiled file
1265cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * and the header data is read and merged into the final ResourceTable.
1266cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   *
1267cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * All other file types are ignored. This is because these files could be
1268cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * coming from a zip,
1269cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * where we could have other files like classes.dex.
1270cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool MergeFile(io::IFile* file, bool override) {
1272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const Source& src = file->GetSource();
1273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::EndsWith(src.path, ".arsc.flat")) {
1274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return MergeResourceTable(file, override);
1275cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::EndsWith(src.path, ".flat")) {
1277cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Try opening the file and looking for an Export header.
1278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
1279cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!data) {
1280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open");
1281cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1282cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
128336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      CompiledFileInputStream input_stream(data->data(), data->size());
1285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      uint32_t num_files = 0;
1286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!input_stream.ReadLittleEndian32(&num_files)) {
1287d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files");
1288cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1289cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
129036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (uint32_t i = 0; i < num_files; i++) {
1292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        pb::CompiledFile compiled_file;
1293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadCompiledFile(&compiled_file)) {
1294d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src)
1295d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to read compiled file header");
1296cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
129736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
129836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1299cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        uint64_t offset, len;
1300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input_stream.ReadDataMetaData(&offset, &len)) {
1301d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data");
1302cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
130336c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
130436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1305d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb(
1306d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            compiled_file, file->GetSource(), context_->GetDiagnostics());
1307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!resource_file) {
1308cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
130936c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
131036c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1311d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(),
1312d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                               override)) {
1313cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return false;
131436c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1315cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1316cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return true;
1317d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
13186a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // Since AAPT compiles these file types and appends .flat to them, seeing
13196a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      // their raw extensions is a sign that they weren't compiled.
1320d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
1321d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type
1322d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                         << " file passed as argument. Must be "
1323d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                                            "compiled first into .flat file.");
13246a396c1abb4e52f5a8fed5fab204ebc7b8e16decAdam Lesinski      return false;
132536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski    }
132636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1327cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Ignore non .flat files. This could be classes.dex or something else that
1328cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // happens
1329cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // to be in an archive.
1330cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1331cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1332cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1333b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  bool CopyAssetsDirsToApk(IArchiveWriter* writer) {
1334b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets;
1335b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (const std::string& assets_dir : options_.assets_dirs) {
1336b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      Maybe<std::vector<std::string>> files =
1337b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr);
1338b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (!files) {
1339b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1340b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1341b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1342b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      for (const std::string& file : files.value()) {
1343b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_key = "assets/" + file;
1344b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        std::string full_path = assets_dir;
1345b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        file::AppendPath(&full_path, file);
1346b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1347b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        auto iter = merged_assets.find(full_key);
1348b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        if (iter == merged_assets.end()) {
1349b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          merged_assets.emplace(std::move(full_key),
1350b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                util::make_unique<io::RegularFile>(Source(std::move(full_path))));
1351b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        } else if (context_->IsVerbose()) {
1352b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource())
1353b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                           << "asset file overrides '" << full_path << "'");
1354b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        }
1355b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1356b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1357b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1358b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    for (auto& entry : merged_assets) {
1359b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      uint32_t compression_flags = ArchiveEntry::kCompress;
1360b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      std::string extension = file::GetExtension(entry.first).to_string();
1361b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      if (options_.extensions_to_not_compress.count(extension) > 0) {
1362b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        compression_flags = 0u;
1363b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1364b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1365d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags,
1366d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                 writer)) {
1367b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski        return false;
1368b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      }
1369b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1370b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    return true;
1371b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski  }
1372b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1373cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  /**
1374cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   * Writes the AndroidManifest, ResourceTable, and all XML files referenced by
1375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski   * the ResourceTable to the IArchiveWriter.
1376cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski   */
1377d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
1378d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                ResourceTable* table) {
1379b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    const bool keep_raw_values = context_->GetPackageType() == PackageType::kStaticLib;
1380c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    bool result = FlattenXml(context_, manifest, "AndroidManifest.xml", keep_raw_values, writer);
1381cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!result) {
1382cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1383cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1384cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ResourceFileFlattenerOptions file_flattener_options;
1386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.keep_raw_values = keep_raw_values;
1387d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
1388d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
1389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_auto_version = options_.no_auto_version;
1390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_version_vectors = options_.no_version_vectors;
13914d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    file_flattener_options.no_version_transitions = options_.no_version_transitions;
1392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
1393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    file_flattener_options.update_proguard_spec =
1394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        static_cast<bool>(options_.generate_proguard_rules_path);
1395cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1396ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski    ResourceFileFlattener file_flattener(file_flattener_options, context_, keep_set);
1397cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!file_flattener.Flatten(table, writer)) {
1399ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking file resources");
1400cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return false;
1401cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1402cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1403b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTableToPb(table, writer)) {
1405cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1406cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1407cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!FlattenTable(table, writer)) {
1409ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resources.arsc");
1410cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return false;
1411cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1412cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1413cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return true;
1414cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
14159ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
1416ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  int Run(const std::vector<std::string>& input_files) {
1417cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Load the AndroidManifest.xml
1418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<xml::XmlResource> manifest_xml =
1419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LoadXml(options_.manifest_path, context_->GetDiagnostics());
1420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_xml) {
1421cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1422cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1424d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    // First extract the Package name without modifying it (via --rename-manifest-package).
1425d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (Maybe<AppInfo> maybe_app_info =
1426d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) {
1427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const AppInfo& app_info = maybe_app_info.value();
1428ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetCompilationPackage(app_info.package);
1429cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1430fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ManifestFixer manifest_fixer(options_.manifest_fixer_options);
1432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!manifest_fixer.Consume(context_, manifest_xml.get())) {
1433cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1434cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1436d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<AppInfo> maybe_app_info =
1437d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics());
1438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!maybe_app_info) {
1439cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1440cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const AppInfo& app_info = maybe_app_info.value();
1443d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0));
14441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1445d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});
1446f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1447f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    // Override the package ID when it is "android".
1448f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (context_->GetCompilationPackage() == "android") {
1449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->SetPackageId(0x01);
1450f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
1451f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      // Verify we're building a regular app.
1452b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() != PackageType::kApp) {
1453f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        context_->GetDiagnostics()->Error(
1454f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski            DiagMessage() << "package 'android' can only be built as a regular app");
1455f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski        return 1;
1456f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      }
1457cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadSymbolsFromIncludePaths()) {
1460cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1461cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    TableMergerOptions table_merger_options;
1464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    table_merger_options.auto_add_overlay = options_.auto_add_overlay;
1465d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);
14661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (context_->IsVerbose()) {
1468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context_->GetDiagnostics()->Note(DiagMessage()
1469f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                       << StringPrintf("linking package '%s' using package ID %02x",
1470f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetCompilationPackage().data(),
1471f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                       context_->GetPackageId()));
1472cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1473bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : input_files) {
1475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, false)) {
1476d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input");
1477cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1478cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1479cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const std::string& input : options_.overlay_files) {
1482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!MergePath(input, true)) {
1483d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays");
1484cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1485cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1486cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
148764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!VerifyNoExternalPackages()) {
1489cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1490cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
14911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1492b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() != PackageType::kStaticLib) {
1493cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      PrivateAttributeMover mover;
1494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!mover.Consume(context_, &final_table_)) {
1495d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes");
1496cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1497cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
149836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1499cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Assign IDs if we are building a regular app.
1500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      IdAssigner id_assigner(&options_.stable_id_map);
1501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!id_assigner.Consume(context_, &final_table_)) {
1502ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed assigning IDs");
1503cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1504cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
150536c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1506cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now grab each ID and emit it as a file.
1507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.resource_id_map_path) {
1508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        for (auto& package : final_table_.packages) {
1509cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          for (auto& type : package->types) {
1510cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            for (auto& entry : type->entries) {
1511cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              ResourceName name(package->name, type->type, entry->name);
1512cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski              // The IDs are guaranteed to exist.
1513d0f492db038c6210c1138865d816bfb134376538Adam Lesinski              options_.stable_id_map[std::move(name)] =
1514d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                  ResourceId(package->id.value(), type->id.value(), entry->id.value());
15151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
1516cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
151736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
151836c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1519d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map,
1520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                    options_.resource_id_map_path.value())) {
1521cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
152236c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski        }
1523cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1524cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1525cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Static libs are merged with other apps, and ID collisions are bad, so
1526cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // verify that
1527cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // no IDs have been set.
1528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!VerifyNoIdsSet()) {
1529cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1530cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1531cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1532cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1533cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add the names to mangle based on our source merge earlier.
1534d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context_->SetNameManglerPolicy(
1535d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()});
1536cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1537cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Add our table to the symbol table.
1538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context_->GetExternalSymbols()->PrependSource(
1539ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        util::make_unique<ResourceTableSymbolSource>(&final_table_));
1540cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
15411e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // Workaround for pre-O runtime that would treat negative resource IDs
15421e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // (any ID with a package ID > 7f) as invalid. Intercept any ID (PPTTEEEE) with PP > 0x7f
15431e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // and type == 'id', and return the ID 0x7fPPEEEE. IDs don't need to be real resources, they
15441e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    // are just identifiers.
15451e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    if (context_->GetMinSdkVersion() < SDK_O && context_->GetPackageType() == PackageType::kApp) {
15461e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      if (context_->IsVerbose()) {
15471e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski        context_->GetDiagnostics()->Note(DiagMessage()
15481e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski                                         << "enabling pre-O feature split ID rewriting");
15491e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      }
15501e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski      context_->GetExternalSymbols()->SetDelegate(
15511e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski          util::make_unique<FeatureSplitSymbolTableDelegate>(context_));
15521e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski    }
15531e4b0e54a3db31bdbcb9385bf22bab4b96096d1fAdam Lesinski
1554cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ReferenceLinker linker;
1555ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!linker.Consume(context_, &final_table_)) {
1556d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references");
1557cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1558cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1559cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1560b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1561ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!options_.products.empty()) {
1562ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1563ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't select products when building static library");
1564cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1565cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1566ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      ProductFilter product_filter(options_.products);
1567ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!product_filter.Consume(context_, &final_table_)) {
1568ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed stripping products");
1569cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1570cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1571cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
157236c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1573ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_auto_version) {
1574cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      AutoVersioner versioner;
1575ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!versioner.Consume(context_, &final_table_)) {
1576d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles");
1577cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1578cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1579cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
158077788eb4cf0c5dba0f7370192e40364fe853050aAlexandria Cornwall
1581b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) {
1582ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (context_->IsVerbose()) {
1583d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context_->GetDiagnostics()->Note(DiagMessage()
1584d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << "collapsing resource versions for minimum SDK "
1585d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << context_->GetMinSdkVersion());
1586cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
158736c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1588cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      VersionCollapser collapser;
1589ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!collapser.Consume(context_, &final_table_)) {
1590cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1591cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1592cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1593355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1594ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!options_.no_resource_deduping) {
1595cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      ResourceDeduper deduper;
1596ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!deduper.Consume(context_, &final_table_)) {
1597ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
1598cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1599cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1600cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1601cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1602ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_keep_set;
1603ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    proguard::KeepSet proguard_main_dex_keep_set;
1604cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1605b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context_->GetPackageType() == PackageType::kStaticLib) {
1606ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.table_splitter_options.config_filter != nullptr ||
1607672384b41e1fc7195424533b7aa6753fb771a6cbPierre Lecesne          !options_.table_splitter_options.preferred_densities.empty()) {
1608ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski        context_->GetDiagnostics()->Warn(DiagMessage()
1609ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski                                         << "can't strip resources when building static library");
1610cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1611cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1612d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
1613d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      // equal to the minSdk.
1614d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      options_.split_constraints =
1615d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
1616cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1617d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
1618ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!table_splitter.VerifySplitConstraints(context_)) {
1619cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1620cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1621ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      table_splitter.SplitTable(&final_table_);
1622cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1623cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Now we need to write out the Split APKs.
1624ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      auto path_iter = options_.split_paths.begin();
1625d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      auto split_constraints_iter = options_.split_constraints.begin();
1626d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) {
1627ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (context_->IsVerbose()) {
1628d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Note(DiagMessage(*path_iter)
1629d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "generating split with configurations '"
1630d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << util::Joiner(split_constraints_iter->configs, ", ")
1631d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                           << "'");
16321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1634d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter);
1635ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!archive_writer) {
1636d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1637cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
16381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1640cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Generate an AndroidManifest.xml for each split.
1641ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<xml::XmlResource> split_manifest =
1642ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            GenerateSplitManifest(app_info, *split_constraints_iter);
16431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1644cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        XmlReferenceLinker linker;
1645ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!linker.Consume(context_, split_manifest.get())) {
1646d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context_->GetDiagnostics()->Error(DiagMessage()
1647d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                            << "failed to create Split AndroidManifest.xml");
1648cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1649467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        }
1650467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
1651d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(),
1652d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                      split_table.get())) {
1653cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1654637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall        }
1655637b4820dc1858dacbf562ca65c13b4be0249e0eAlexandria Cornwall
1656ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++path_iter;
1657ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        ++split_constraints_iter;
1658cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1659cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
16609e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1661cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Start writing the base APK.
1662b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(options_.output_path);
1663ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!archive_writer) {
1664b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
1665cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1666cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
16679e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski
1668cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    bool error = false;
1669cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    {
1670cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // AndroidManifest.xml has no resource name, but the CallSite is built
1671cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // from the name
1672cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // (aka, which package the AndroidManifest.xml is coming from).
1673cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // So we give it a package name so it can see local resources.
1674ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      manifest_xml->file.name.package = context_->GetCompilationPackage();
1675ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1676ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      XmlReferenceLinker manifest_linker;
1677ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (manifest_linker.Consume(context_, manifest_xml.get())) {
1678ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_proguard_rules_path &&
1679b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1680b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(), &proguard_keep_set)) {
1681cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
16821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1684ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_main_dex_proguard_rules_path &&
1685b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski            !proguard::CollectProguardRulesForManifest(Source(options_.manifest_path),
1686b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       manifest_xml.get(),
1687b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                                                       &proguard_main_dex_keep_set, true)) {
1688cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          error = true;
1689e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal        }
1690e49bb30dab4c37926962e8b408045e5a45f52c40Rohit Agrawal
1691ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.generate_java_class_path) {
1692ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!WriteManifestJavaFile(manifest_xml.get())) {
1693cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1694cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
16951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
16961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1697ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (options_.no_xml_namespaces) {
1698cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // PackageParser will fail if URIs are removed from
1699cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          // AndroidManifest.xml.
1700ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          XmlNamespaceRemover namespace_remover(true /* keepUris */);
1701ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (!namespace_remover.Consume(context_, manifest_xml.get())) {
1702cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            error = true;
1703cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          }
17041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1705cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      } else {
1706cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        error = true;
1707cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
17081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1709fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1710cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (error) {
1711b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      context_->GetDiagnostics()->Error(DiagMessage() << "failed processing manifest");
1712cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1713cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1714a6fe345be955368a13aea76aefb4db821aad11dfAdam Lesinski
1715b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(), &final_table_)) {
1716b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski      return 1;
1717b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    }
1718b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski
1719b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski    if (!CopyAssetsDirsToApk(archive_writer.get())) {
1720cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1721cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1722fb48d292d9eb78a73f9473d90911ecb81da5fffdAdam Lesinski
1723ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (options_.generate_java_class_path) {
1724b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // The set of packages whose R class to call in the main classes
1725b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // onResourcesLoaded callback.
1726b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      std::vector<std::string> packages_to_callback;
1727b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1728b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions template_options;
1729b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1730b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      template_options.javadoc_annotations = options_.javadoc_annotations;
1731fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1732b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() == PackageType::kStaticLib ||
1733b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski          options_.generate_non_final_ids) {
1734b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1735ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski      }
1736ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1737b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski      if (context_->GetPackageType() == PackageType::kSharedLib) {
1738b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.use_final = false;
1739b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
1740cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
174164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1742ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const StringPiece actual_package = context_->GetCompilationPackage();
1743ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      StringPiece output_package = context_->GetCompilationPackage();
1744ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.custom_java_package) {
1745cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // Override the output java package to the custom one.
1746ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        output_package = options_.custom_java_package.value();
1747cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
17481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1749b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the private symbols if required.
1750ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (options_.private_symbols) {
1751b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(options_.private_symbols.value());
1752b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1753cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // If we defined a private symbols package, we only emit Public symbols
1754cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // to the original package, and private and public symbols to the
1755cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        // private package.
1756b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1757b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
1758b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
1759b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski                           options)) {
1760b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski          return 1;
1761b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        }
1762b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
17631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1764b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate all the symbols for all extra packages.
1765b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      for (const std::string& extra_package : options_.extra_java_packages) {
1766b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        packages_to_callback.push_back(extra_package);
1767b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1768b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        JavaClassGeneratorOptions options = template_options;
1769b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
1770b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
1771cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski          return 1;
1772c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski        }
1773b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      }
17741e21ff00b005110128245a4b0d13a7513a2d5e0cAdam Lesinski
1775b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Generate the main public R class.
1776b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      JavaClassGeneratorOptions options = template_options;
1777b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski
1778b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      // Only generate public symbols if we have a private package.
1779b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options_.private_symbols) {
1780b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
1781cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1782c51562cf5acda7849a34c4ae2a88077c068859c0Adam Lesinski
1783b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski      if (options.rewrite_callback_options) {
1784b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        options.rewrite_callback_options.value().packages_to_callback =
1785b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski            std::move(packages_to_callback);
1786cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
178764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
1788418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski      if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
1789418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                         options_.generate_text_symbols_path)) {
1790b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski        return 1;
1791cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1792fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski    }
1793fc9570e6b0a6304abe6e6c52613516e93cf9251fAdam Lesinski
1794b5dc4bd49a036e3403ca17e961d2c8e13e038295Adam Lesinski    if (!WriteProguardFile(options_.generate_proguard_rules_path, proguard_keep_set)) {
1795cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1796e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski    }
1797e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski
1798ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path,
1799ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                           proguard_main_dex_keep_set)) {
1800cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
1801cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1802cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 0;
1803cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1804355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1805cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
1806ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkOptions options_;
1807ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  LinkContext* context_;
1808ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResourceTable final_table_;
1809355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1810ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<TableMerger> table_merger_;
1811355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
1812cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A pointer to the FileCollection representing the filesystem (not archives).
1813ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<io::FileCollection> file_collection_;
18146a008170cb18666e04c42856f992fc7a0afa1e1fAdam Lesinski
1815cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of IFileCollections. This is mainly here to keep ownership of the
1816cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // collections.
1817ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<io::IFileCollection>> collections_;
1818bf0bd0f9ac1ffa0231cff0f6591dede48b3c6d52Adam Lesinski
1819cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // A vector of ResourceTables. This is here to retain ownership, so that the
1820ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // SymbolTable can use these.
1821ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::unique_ptr<ResourceTable>> static_table_includes_;
1822ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski
1823ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  // The set of shared libraries being used, mapping their assigned package ID to package name.
1824ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  std::map<size_t, std::string> shared_libs_;
1825cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski};
182636c73a595910e96f3552f938eeb81d46356067a1Adam Lesinski
1827820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warringtonint Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
1828820d72adc0eccbfe4ac4238cdc89b7680ea03d9eChris Warrington  LinkContext context(diagnostics);
1829cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkOptions options;
1830ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> overlay_arg_list;
1831ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> extra_java_packages;
1832f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  Maybe<std::string> package_id;
1833113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski  std::vector<std::string> configs;
1834ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> preferred_density;
1835ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> product_list;
1836ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool legacy_x_flag = false;
1837ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool require_localization = false;
1838cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool verbose = false;
1839ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool shared_lib = false;
1840ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  bool static_lib = false;
1841ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<std::string> stable_id_file_path;
1842ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> split_args;
1843cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Flags flags =
1844cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      Flags()
1845d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("-o", "Output path.", &options.output_path)
1846d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .RequiredFlag("--manifest", "Path to the Android manifest to build.",
1847ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_path)
1848d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths)
1849b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski          .OptionalFlagList("-A",
1850b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            "An assets directory to include in the APK. These are unprocessed.",
1851b39ad7c9f66877f92ea8583aa8b7b5a8daa6031eAdam Lesinski                            &options.assets_dirs)
1852c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("-R",
1853c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "Compilation unit to link, using `overlay` semantics.\n"
1854c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            "The last conflicting resource given takes precedence.",
1855c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &overlay_arg_list)
1856f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          .OptionalFlag("--package-id",
1857f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "Specify the package ID to use for this app. Must be greater or equal to\n"
1858f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        "0x7f and can't be used with --static-lib or --shared-lib.",
1859f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                        &package_id)
1860d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--java", "Directory in which to generate R.java.",
1861ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_java_class_path)
1862d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--proguard", "Output file for generated Proguard rules.",
1863ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.generate_proguard_rules_path)
1864c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--proguard-main-dex",
1865d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Output file for generated Proguard rules for the main dex.",
1866c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.generate_main_dex_proguard_rules_path)
1867d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--no-auto-version",
1868d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic style and layout SDK versioning.",
1869ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_auto_version)
1870ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-version-vectors",
1871d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of vector drawables. Use this only\n"
1872d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with vector drawable support library.",
1873ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_version_vectors)
18744d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki          .OptionalSwitch("--no-version-transitions",
1875d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Disables automatic versioning of transition resources. Use this only\n"
1876d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "when building with transition support library.",
18774d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki                          &options.no_version_transitions)
1878ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-resource-deduping",
1879cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "Disables automatic deduping of resources with\n"
1880cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                          "identical values across compatible configurations.",
1881ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_resource_deduping)
1882c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalSwitch("--enable-sparse-encoding",
1883c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "Enables encoding sparse entries using a binary search tree.\n"
1884c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          "This decreases APK size at the cost of resource retrieval performance.",
1885c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &options.table_flattener_options.use_sparse_entries)
1886d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
1887c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                          &legacy_x_flag)
1888d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
1889ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &require_localization)
1890113ee097386380daa8f01d74916504a9a1338a63Adam Lesinski          .OptionalFlagList("-c",
1891418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            "Comma separated list of configurations to include. The default\n"
1892418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            "is all configurations.",
1893418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                            &configs)
1894c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--preferred-density",
1895c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        "Selects the closest matching density and strips out all others.",
1896c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &preferred_density)
1897c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
1898ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--output-to-dir",
1899d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Outputs the APK contents to a directory specified by -o.",
1900ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.output_to_directory)
1901ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-xml-namespaces",
1902d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Removes XML namespace prefix and URI information from\n"
1903d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "AndroidManifest.xml and XML binaries in res/*.",
1904ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_xml_namespaces)
1905ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--min-sdk-version",
1906d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default minimum SDK version to use for AndroidManifest.xml.",
1907ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.min_sdk_version_default)
1908c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--target-sdk-version",
1909d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Default target SDK version to use for AndroidManifest.xml.",
1910c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.target_sdk_version_default)
1911ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-code",
1912d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
1913d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "present.",
1914ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_code_default)
1915ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--version-name",
1916d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Version name to inject into the AndroidManifest.xml if none is present.",
1917ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.version_name_default)
1918d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
1919d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          &shared_lib)
1920d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
1921ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--no-static-lib-packages",
1922d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Merge all library resources under the app's package.",
1923ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.no_static_lib_packages)
1924ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--non-final-ids",
1925d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Generates R.java without the final modifier. This is implied when\n"
1926d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "--static-lib is specified.",
1927ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.generate_non_final_ids)
1928c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
1929ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &stable_id_file_path)
1930c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--emit-ids",
1931d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Emit a file at the given path with a list of name to ID mappings,\n"
1932d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "suitable for use with --stable-ids.",
1933c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.resource_id_map_path)
1934ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlag("--private-symbols",
1935d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Package name to use when generating R.java for private symbols.\n"
1936d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "If not specified, public and private symbols will use the application's\n"
1937d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "package name.",
1938ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.private_symbols)
1939d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
1940ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.custom_java_package)
1941ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--extra-packages",
1942d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Generate the same R.java but with different package names.",
1943ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &extra_java_packages)
1944ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalFlagList("--add-javadoc-annotation",
1945d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Adds a JavaDoc annotation to all generated Java classes.",
1946ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.javadoc_annotations)
1947418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski          .OptionalFlag("--output-text-symbols",
1948418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        "Generates a text file containing the resource symbols of the R class in\n"
1949418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        "the specified folder.",
1950418763ff54170484c527bf618ef2fad34fe63f97Adam Lesinski                        &options.generate_text_symbols_path)
1951ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          .OptionalSwitch("--auto-add-overlay",
1952d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "Allows the addition of new resources in overlays without\n"
1953d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                          "<add-resource> tags.",
1954ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                          &options.auto_add_overlay)
1955d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
1956ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                        &options.manifest_fixer_options.rename_manifest_package)
1957c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlag("--rename-instrumentation-target-package",
1958d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "Changes the name of the target package for instrumentation. Most useful\n"
1959d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                        "when used in conjunction with --rename-manifest-package.",
1960c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                        &options.manifest_fixer_options.rename_instrumentation_target_package)
1961d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalFlagList("-0", "File extensions not to compress.",
1962ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                            &options.extensions_to_not_compress)
1963c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski          .OptionalFlagList("--split",
1964d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                            "Split resources matching a set of configs out to a Split APK.\n"
1965db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski                            "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
1966db091577fff5bcddac703bc8ac4f932fd53e0621Adam Lesinski                            "On Windows, use a semicolon ';' separator instead.",
1967c8f71aa67ea599cb80205496cb67e9e7a121299cAdam Lesinski                            &split_args)
1968d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
1969cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1970ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flags.Parse("aapt2 link", args, &std::cerr)) {
1971cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 1;
1972cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1973cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1974d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Expand all argument-files passed into the command line. These start with '@'.
1975ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<std::string> arg_list;
1976ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : flags.GetArgs()) {
1977ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1978cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1979cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1980ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &arg_list, &error)) {
1981ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1982cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1983cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1984cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1985ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      arg_list.push_back(arg);
1986cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1987cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1988cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1989cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Expand all argument-files passed to -R.
1990ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : overlay_arg_list) {
1991ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (util::StartsWith(arg, "@")) {
1992cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      const std::string path = arg.substr(1, arg.size() - 1);
1993cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      std::string error;
1994ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) {
1995ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        context.GetDiagnostics()->Error(DiagMessage(path) << error);
1996cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        return 1;
1997cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
1998cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    } else {
1999ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      options.overlay_files.push_back(arg);
2000cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2001cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2002cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2003cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (verbose) {
2004ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    context.SetVerbose(verbose);
2005cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2006cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2007f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib && static_lib) {
2008f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.GetDiagnostics()->Error(DiagMessage()
2009f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                    << "only one of --shared-lib and --static-lib can be defined");
2010f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    return 1;
2011f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
2012f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2013f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (shared_lib) {
2014b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kSharedLib);
2015f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(0x00);
2016f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else if (static_lib) {
2017b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kStaticLib);
2018f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
2019f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  } else {
2020b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    context.SetPackageType(PackageType::kApp);
2021f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(kAppPackageId);
2022f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
2023f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2024f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  if (package_id) {
2025b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    if (context.GetPackageType() != PackageType::kApp) {
2026f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
2027f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << "can't specify --package-id when not building a regular app");
2028f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2029f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2030f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2031f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id.value());
2032f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (!maybe_package_id_int) {
2033f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id.value()
2034f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski                                                    << "' is not a valid integer");
2035f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2036f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2037f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2038f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    const uint32_t package_id_int = maybe_package_id_int.value();
2039f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
2040f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      context.GetDiagnostics()->Error(
2041f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski          DiagMessage() << StringPrintf(
2042f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski              "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
2043f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski      return 1;
2044f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    }
2045f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski    context.SetPackageId(static_cast<uint8_t>(package_id_int));
2046f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski  }
2047f34b6f4f2b969b47a3f371eb9549e92ef1680d91Adam Lesinski
2048cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate the set of extra packages for which to generate R.java.
2049ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (std::string& extra_package : extra_java_packages) {
2050cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // A given package can actually be a colon separated list of packages.
2051ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece package : util::Split(extra_package, ':')) {
2052d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski      options.extra_java_packages.insert(package.to_string());
2053cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2054cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2055cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2056ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (product_list) {
2057ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
2058cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (product != "" && product != "default") {
2059d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski        options.products.insert(product.to_string());
2060cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
2061cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2062cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2063cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2064d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<IConfigFilter> filter;
2065f4dacf29cc995fad4aea8e8f25811f9ee4685d91Mihai Nita  if (!configs.empty()) {
2066d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
2067d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (filter == nullptr) {
2068d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      return 1;
2069cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2070d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.config_filter = filter.get();
2071cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2072cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2073ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (preferred_density) {
2074d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    Maybe<uint16_t> density =
2075d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics());
2076d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!density) {
2077cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2078cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2079d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.table_splitter_options.preferred_densities.push_back(density.value());
2080d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
2081cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2082d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  // Parse the split parameters.
2083d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  for (const std::string& split_arg : split_args) {
2084d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_paths.push_back({});
2085d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    options.split_constraints.push_back({});
2086d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
2087d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                             &options.split_constraints.back())) {
2088cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2089cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2090cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2091cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2092b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  if (context.GetPackageType() != PackageType::kStaticLib && stable_id_file_path) {
2093ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
2094ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                         &options.stable_id_map)) {
2095cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      return 1;
2096cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
2097cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2098cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2099cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Populate some default no-compress extensions that are already compressed.
2100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  options.extensions_to_not_compress.insert(
2101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
2102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
2103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
2104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
2105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // Turn off auto versioning for static-libs.
2107b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  if (context.GetPackageType() == PackageType::kStaticLib) {
2108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_auto_version = true;
2109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.no_version_vectors = true;
21104d35cca96ce55eb29d1948086214f91ae94e9adbYuichi Araki    options.no_version_transitions = true;
2111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
2112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
2113cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  LinkCommand cmd(&context, options);
2114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return cmd.Run(arg_list);
21151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
21161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2117cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
2118