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