diff options
Diffstat (limited to 'tools')
38 files changed, 375 insertions, 287 deletions
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 5f664f5fdd5c..98324850f3f5 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -435,7 +435,7 @@ void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* const size_t NS = pool->size(); for (size_t s=0; s<NS; s++) { String8 str = pool->string8ObjectAt(s); - printer->Print(StringPrintf("String #%zd: %s\n", s, str.string())); + printer->Print(StringPrintf("String #%zd : %s\n", s, str.string())); } } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 2f8ca2d62061..d0237f80a8f0 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -1084,7 +1084,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource // Create a overlayable entry grouping that represents this <overlayable> auto overlayable = std::make_shared<Overlayable>( overlayable_name.value(), (overlayable_actor) ? overlayable_actor.value() : "", - out_resource->source); + source_); bool error = false; std::string comment; @@ -1113,6 +1113,13 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource const std::string& element_name = parser->element_name(); const std::string& element_namespace = parser->element_namespace(); if (element_namespace.empty() && element_name == "item") { + if (current_policies == OverlayableItem::Policy::kNone) { + diag_->Error(DiagMessage(element_source) + << "<item> within an <overlayable> must be inside a <policy> block"); + error = true; + continue; + } + // Items specify the name and type of resource that should be overlayable Maybe<StringPiece> item_name = xml::FindNonEmptyAttribute(parser, "name"); if (!item_name) { @@ -1169,6 +1176,8 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource current_policies |= OverlayableItem::Policy::kSystem; } else if (trimmed_part == "vendor") { current_policies |= OverlayableItem::Policy::kVendor; + } else if (trimmed_part == "signature") { + current_policies |= OverlayableItem::Policy::kSignature; } else { diag_->Error(DiagMessage(element_source) << "<policy> has unsupported type '" << trimmed_part << "'"); @@ -1176,6 +1185,11 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource continue; } } + } else { + diag_->Error(DiagMessage(element_source) + << "<policy> must have a 'type' attribute"); + error = true; + continue; } } else if (!ShouldIgnoreElement(element_namespace, element_name)) { diag_->Error(DiagMessage(element_source) << "invalid element <" << element_name << "> " @@ -1623,7 +1637,9 @@ bool ResourceParser::ParsePlural(xml::XmlPullParser* parser, if (!(plural->values[index] = ParseXml( parser, android::ResTable_map::TYPE_STRING, kNoRawString))) { error = true; + continue; } + plural->values[index]->SetSource(item_source); } else if (!ShouldIgnoreElement(element_namespace, element_name)) { diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 827c7deaf452..25b76b0c1fa0 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -894,8 +894,10 @@ TEST_F(ResourceParserTest, ParsePlatformIndependentNewline) { TEST_F(ResourceParserTest, ParseOverlayable) { std::string input = R"( <overlayable name="Name" actor="overlay://theme"> - <item type="string" name="foo" /> - <item type="drawable" name="bar" /> + <policy type="signature"> + <item type="string" name="foo" /> + <item type="drawable" name="bar" /> + </policy> </overlayable>)"; ASSERT_TRUE(TestParse(input)); @@ -906,7 +908,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) { OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar")); ASSERT_TRUE(search_result); @@ -915,7 +917,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) { result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); } TEST_F(ResourceParserTest, ParseOverlayableRequiresName) { @@ -931,7 +933,6 @@ TEST_F(ResourceParserTest, ParseOverlayableBadActorFail) { TEST_F(ResourceParserTest, ParseOverlayablePolicy) { std::string input = R"( <overlayable name="Name"> - <item type="string" name="foo" /> <policy type="product"> <item type="string" name="bar" /> </policy> @@ -944,23 +945,18 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { <policy type="public"> <item type="string" name="faz" /> </policy> + <policy type="signature"> + <item type="string" name="foz" /> + </policy> </overlayable>)"; ASSERT_TRUE(TestParse(input)); - auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo")); + auto search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); - - search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); - ASSERT_TRUE(search_result); - ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable_item); - result_overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct)); search_result = table_.FindResource(test::ParseNameOrDie("string/fiz")); @@ -986,6 +982,30 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic)); + + search_result = table_.FindResource(test::ParseNameOrDie("string/foz")); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); +} + +TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) { + std::string input = R"( + <overlayable name="Name"> + <item type="string" name="foo" /> + </overlayable>)"; + EXPECT_FALSE(TestParse(input)); + + input = R"( + <overlayable name="Name"> + <policy> + <item name="foo" /> + </policy> + </overlayable>)"; + EXPECT_FALSE(TestParse(input)); } TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 7ca99ea42b50..32dfd260e53c 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -92,6 +92,9 @@ struct OverlayableItem { // The resource can be overlaid by any overlay on the product partition. kProduct = 0x08, + + // The resource can be overlaid by any overlay signed with the same signature as its actor. + kSignature = 0x010, }; std::shared_ptr<Overlayable> overlayable; diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index ab4805f626a5..0032960ff93e 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -727,7 +727,7 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config // This must be a FileReference. std::unique_ptr<FileReference> file_ref = util::make_unique<FileReference>(dst_pool->MakeRef( - str, StringPool::Context(StringPool::Context::kHighPriority, config), data)); + str, StringPool::Context(StringPool::Context::kHighPriority, config))); if (type == ResourceType::kRaw) { file_ref->type = ResourceFile::Type::kUnknown; } else if (util::EndsWith(*file_ref->path, ".xml")) { @@ -739,7 +739,7 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config } // There are no styles associated with this string, so treat it as a simple string. - return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config), data)); + return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config))); } } break; diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 73b568e77689..a2fd7c664b04 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -138,10 +138,10 @@ message AllowNew { // Represents a set of overlayable resources. message Overlayable { - // The name of the <overlyabale>. + // The name of the <overlayable>. string name = 1; - // The location of the <overlyabale> declaration in the source. + // The location of the <overlayable> declaration in the source. Source source = 2; // The component responsible for enabling and disabling overlays targeting this <overlayable>. @@ -151,10 +151,12 @@ message Overlayable { // Represents an overlayable <item> declaration within an <overlayable> tag. message OverlayableItem { enum Policy { - PUBLIC = 0; - SYSTEM = 1; - VENDOR = 2; - PRODUCT = 3; + NONE = 0; + PUBLIC = 1; + SYSTEM = 2; + VENDOR = 3; + PRODUCT = 4; + SIGNATURE = 5; } // The location of the <item> declaration in source. diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp index a8c26668b3a5..8eabd3225d87 100644 --- a/tools/aapt2/StringPool.cpp +++ b/tools/aapt2/StringPool.cpp @@ -165,13 +165,12 @@ StringPool::Ref StringPool::MakeRef(const StringPiece& str) { return MakeRefImpl(str, Context{}, true); } -StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context, - Maybe<size_t> index) { - return MakeRefImpl(str, context, true, index); +StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context) { + return MakeRefImpl(str, context, true); } StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& context, - bool unique, Maybe<size_t> index) { + bool unique) { if (unique) { auto range = indexed_strings_.equal_range(str); for (auto iter = range.first; iter != range.second; ++iter) { @@ -181,26 +180,15 @@ StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& c } } - const size_t size = strings_.size(); - // Insert the string at the end of the string vector if no index is specified - const size_t insertion_index = index ? index.value() : size; - std::unique_ptr<Entry> entry(new Entry()); entry->value = str.to_string(); entry->context = context; - entry->index_ = insertion_index; + entry->index_ = strings_.size(); entry->ref_ = 0; entry->pool_ = this; Entry* borrow = entry.get(); - if (insertion_index == size) { - strings_.emplace_back(std::move(entry)); - } else { - // Allocate enough space for the string at the index - strings_.resize(std::max(insertion_index + 1, size)); - strings_[insertion_index] = std::move(entry); - } - + strings_.emplace_back(std::move(entry)); indexed_strings_.insert(std::make_pair(StringPiece(borrow->value), borrow)); return Ref(borrow); } diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h index 115d5d315b8f..1006ca970dc5 100644 --- a/tools/aapt2/StringPool.h +++ b/tools/aapt2/StringPool.h @@ -166,8 +166,7 @@ class StringPool { // Adds a string to the pool, unless it already exists, with a context object that can be used // when sorting the string pool. Returns a reference to the string in the pool. - Ref MakeRef(const android::StringPiece& str, const Context& context, - Maybe<size_t> index = {}); + Ref MakeRef(const android::StringPiece& str, const Context& context); // Adds a string from another string pool. Returns a reference to the string in the string pool. Ref MakeRef(const Ref& ref); @@ -211,8 +210,7 @@ class StringPool { static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8, IDiagnostics* diag); - Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique, - Maybe<size_t> index = {}); + Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique); void ReAssignIndices(); std::vector<std::unique_ptr<Entry>> strings_; diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp index 648be7d33754..9a7238b584ba 100644 --- a/tools/aapt2/StringPool_test.cpp +++ b/tools/aapt2/StringPool_test.cpp @@ -84,24 +84,6 @@ TEST(StringPoolTest, MaintainInsertionOrderIndex) { EXPECT_THAT(ref_c.index(), Eq(2u)); } -TEST(StringPoolTest, AssignStringIndex) { - StringPool pool; - - StringPool::Ref ref_a = pool.MakeRef("0", StringPool::Context{}, 0u); - StringPool::Ref ref_b = pool.MakeRef("1", StringPool::Context{}, 1u); - StringPool::Ref ref_c = pool.MakeRef("5", StringPool::Context{}, 5u); - StringPool::Ref ref_d = pool.MakeRef("2", StringPool::Context{}, 2u); - StringPool::Ref ref_e = pool.MakeRef("4", StringPool::Context{}, 4u); - StringPool::Ref ref_f = pool.MakeRef("3", StringPool::Context{}, 3u); - - EXPECT_THAT(ref_a.index(), Eq(0u)); - EXPECT_THAT(ref_b.index(), Eq(1u)); - EXPECT_THAT(ref_d.index(), Eq(2u)); - EXPECT_THAT(ref_f.index(), Eq(3u)); - EXPECT_THAT(ref_e.index(), Eq(4u)); - EXPECT_THAT(ref_c.index(), Eq(5u)); -} - TEST(StringPoolTest, PruneStringsWithNoReferences) { StringPool pool; diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp index 7a74ba925ba0..0cf86ccdd59f 100644 --- a/tools/aapt2/cmd/Convert.cpp +++ b/tools/aapt2/cmd/Convert.cpp @@ -43,7 +43,8 @@ namespace aapt { class IApkSerializer { public: - IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {} + IApkSerializer(IAaptContext* context, const Source& source) : context_(context), + source_(source) {} virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16, IArchiveWriter* writer, uint32_t compression_flags) = 0; @@ -167,7 +168,7 @@ class ProtoApkSerializer : public IApkSerializer { std::unique_ptr<io::IData> data = file->file->OpenAsData(); if (!data) { context_->GetDiagnostics()->Error(DiagMessage(source_) - << "failed to open file " << *file->path); + << "failed to open file " << *file->path); return false; } @@ -175,7 +176,7 @@ class ProtoApkSerializer : public IApkSerializer { std::unique_ptr<xml::XmlResource> xml = xml::Inflate(data->data(), data->size(), &error); if (xml == nullptr) { context_->GetDiagnostics()->Error(DiagMessage(source_) << "failed to parse binary XML: " - << error); + << error); return false; } @@ -256,9 +257,6 @@ class Context : public IAaptContext { int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer, ApkFormat output_format, TableFlattenerOptions table_flattener_options, XmlFlattenerOptions xml_flattener_options) { - // Do not change the ordering of strings in the values string pool - table_flattener_options.sort_stringpool_entries = false; - unique_ptr<IApkSerializer> serializer; if (output_format == ApkFormat::kBinary) { serializer.reset(new BinaryApkSerializer(context, apk->GetSource(), table_flattener_options, @@ -274,7 +272,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath); if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, output_writer, (manifest != nullptr && manifest->WasCompressed()) - ? ArchiveEntry::kCompress : 0u)) { + ? ArchiveEntry::kCompress : 0u)) { context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) << "failed to serialize AndroidManifest.xml"); return 1; @@ -303,8 +301,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer if (files_written.insert(*file->path).second) { if (!serializer->SerializeFile(file, output_writer)) { context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) - << "failed to serialize file " - << *file->path); + << "failed to serialize file " << *file->path); return 1; } } @@ -338,7 +335,7 @@ int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer if (!io::CopyFileToArchivePreserveCompression(context, file, path, output_writer)) { context->GetDiagnostics()->Error(DiagMessage(apk->GetSource()) - << "failed to copy file " << path); + << "failed to copy file " << path); return 1; } } diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 8463046a80eb..22edd2f2055a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -268,6 +268,7 @@ struct ResourceFileFlattenerOptions { bool update_proguard_spec = false; OutputFormat output_format = OutputFormat::kApk; std::unordered_set<std::string> extensions_to_not_compress; + Maybe<std::regex> regex_to_not_compress; }; // A sampling of public framework resource IDs. @@ -377,11 +378,18 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& } } +// TODO(rtmitchell): turn this function into a variable that points to a method that retrieves the +// compression flag uint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) { if (options_.do_not_compress_anything) { return 0; } + if (options_.regex_to_not_compress + && std::regex_search(str.to_string(), options_.regex_to_not_compress.value())) { + return 0; + } + for (const std::string& extension : options_.extensions_to_not_compress) { if (util::EndsWith(str, extension)) { return 0; @@ -400,7 +408,8 @@ static bool IsTransitionElement(const std::string& name) { static bool IsVectorElement(const std::string& name) { return name == "vector" || name == "animated-vector" || name == "pathInterpolator" || - name == "objectAnimator" || name == "gradient" || name == "animated-selector"; + name == "objectAnimator" || name == "gradient" || name == "animated-selector" || + name == "set"; } template <typename T> @@ -1530,7 +1539,11 @@ class Linker { for (auto& entry : merged_assets) { uint32_t compression_flags = ArchiveEntry::kCompress; std::string extension = file::GetExtension(entry.first).to_string(); - if (options_.extensions_to_not_compress.count(extension) > 0) { + + if (options_.do_not_compress_anything + || options_.extensions_to_not_compress.count(extension) > 0 + || (options_.regex_to_not_compress + && std::regex_search(extension, options_.regex_to_not_compress.value()))) { compression_flags = 0u; } @@ -1558,6 +1571,7 @@ class Linker { file_flattener_options.keep_raw_values = keep_raw_values; file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything; file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress; + file_flattener_options.regex_to_not_compress = options_.regex_to_not_compress; file_flattener_options.no_auto_version = options_.no_auto_version; file_flattener_options.no_version_vectors = options_.no_version_vectors; file_flattener_options.no_version_transitions = options_.no_version_transitions; @@ -2165,6 +2179,20 @@ int LinkCommand::Action(const std::vector<std::string>& args) { } } + if (no_compress_regex) { + std::string regex = no_compress_regex.value(); + if (util::StartsWith(regex, "@")) { + const std::string path = regex.substr(1, regex.size() -1); + std::string error; + if (!file::AppendSetArgsFromFile(path, &options_.extensions_to_not_compress, &error)) { + context.GetDiagnostics()->Error(DiagMessage(path) << error); + return 1; + } + } else { + options_.regex_to_not_compress = GetRegularExpression(no_compress_regex.value()); + } + } + // Populate some default no-compress extensions that are already compressed. options_.extensions_to_not_compress.insert( {".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 590a6bb19e30..1fc149ab41af 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -17,6 +17,8 @@ #ifndef AAPT2_LINK_H #define AAPT2_LINK_H +#include <regex> + #include "Command.h" #include "Diagnostics.h" #include "Resource.h" @@ -63,6 +65,7 @@ struct LinkOptions { bool no_xml_namespaces = false; bool do_not_compress_anything = false; std::unordered_set<std::string> extensions_to_not_compress; + Maybe<std::regex> regex_to_not_compress; // Static lib options. bool no_static_lib_packages = false; @@ -250,6 +253,11 @@ class LinkCommand : public Command { &options_.do_not_compress_anything); AddOptionalSwitch("--keep-raw-values", "Preserve raw attribute values in xml files.", &options_.keep_raw_values); + AddOptionalFlag("--no-compress-regex", + "Do not compress extensions matching the regular expression. Remember to\n" + " use the '$' symbol for end of line. Uses a non case-sensitive\n" + " ECMAScript regular expression grammar.", + &no_compress_regex); AddOptionalSwitch("--warn-manifest-validation", "Treat manifest validation errors as warnings.", &options_.manifest_fixer_options.warn_validation); @@ -283,6 +291,7 @@ class LinkCommand : public Command { std::vector<std::string> configs_; Maybe<std::string> preferred_density_; Maybe<std::string> product_list_; + Maybe<std::string> no_compress_regex; bool legacy_x_flag_ = false; bool require_localization_ = false; bool verbose_ = false; diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index 792120e449ae..e2c65ba74271 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -435,4 +435,11 @@ void SetLongVersionCode(xml::Element* manifest, uint64_t version) { } } +std::regex GetRegularExpression(const std::string &input) { + // Standard ECMAScript grammar plus case insensitive. + std::regex case_insensitive( + input, std::regex_constants::icase | std::regex_constants::ECMAScript); + return case_insensitive; +} + } // namespace aapt diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h index cf1443e30e1f..2a7c62eef678 100644 --- a/tools/aapt2/cmd/Util.h +++ b/tools/aapt2/cmd/Util.h @@ -17,6 +17,8 @@ #ifndef AAPT_SPLIT_UTIL_H #define AAPT_SPLIT_UTIL_H +#include <regex> + #include "androidfw/StringPiece.h" #include "AppInfo.h" @@ -72,6 +74,9 @@ std::string MakePackageSafeName(const std::string &name); // versionCodeMajor if the version code requires more than 32 bits. void SetLongVersionCode(xml::Element* manifest, uint64_t version_code); +// Returns a case insensitive regular expression based on the input. +std::regex GetRegularExpression(const std::string &input); + } // namespace aapt #endif /* AAPT_SPLIT_UTIL_H */ diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp index f92f1e3c4c7e..7e492610b658 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -383,4 +383,12 @@ TEST (UtilTest, AdjustSplitConstraintsForMinSdk) { EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig()); } +TEST(UtilTest, RegularExperssions) { + std::string valid(".bc$"); + std::regex expression = GetRegularExpression(valid); + EXPECT_TRUE(std::regex_search("file.abc", expression)); + EXPECT_TRUE(std::regex_search("file.123bc", expression)); + EXPECT_FALSE(std::regex_search("abc.zip", expression)); +} + } // namespace aapt diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index 40aaa05c2b30..59eb9ec2d418 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -401,7 +401,6 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package, if (entry->flags & ResTable_entry::FLAG_PUBLIC) { Visibility visibility; visibility.level = Visibility::Level::kPublic; - visibility.source = source_.WithLine(0); if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) { return false; } @@ -448,7 +447,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { arraysize(header->name))); overlayable->actor = util::Utf16ToUtf8(strcpy16_dtoh((const char16_t*)header->actor, arraysize(header->name))); - overlayable->source = source_.WithLine(0); ResChunkPullParser parser(GetChunkData(chunk), GetChunkDataLen(chunk)); @@ -473,6 +471,10 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { policies |= OverlayableItem::Policy::kProduct; } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_SIGNATURE) { + policies |= OverlayableItem::Policy::kSignature; + } const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>( ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); @@ -491,7 +493,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { } OverlayableItem overlayable_item(overlayable); - overlayable_item.source = source_.WithLine(0); overlayable_item.policies = policies; if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) { return false; diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index 9d341cc1ca4a..d677317dc98d 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -274,7 +274,9 @@ class PackageFlattener { FlattenLibrarySpec(buffer); } - FlattenOverlayable(buffer); + if (!FlattenOverlayable(buffer)) { + return false; + } pkg_writer.Finish(); return true; @@ -468,23 +470,29 @@ class PackageFlattener { overlayable_chunk = &chunk; } + if (item.policies == 0) { + context_->GetDiagnostics()->Error(DiagMessage(item.overlayable->source) + << "overlayable " + << entry->name + << " does not specify policy"); + return false; + } + uint32_t policy_flags = 0; - if (item.policies == OverlayableItem::Policy::kNone) { - // Encode overlayable entries defined without a policy as publicly overlayable + if (item.policies & OverlayableItem::Policy::kPublic) { policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; - } else { - if (item.policies & OverlayableItem::Policy::kPublic) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; - } - if (item.policies & OverlayableItem::Policy::kSystem) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION; - } - if (item.policies & OverlayableItem::Policy::kVendor) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION; - } - if (item.policies & OverlayableItem::Policy::kProduct) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; - } + } + if (item.policies & OverlayableItem::Policy::kSystem) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION; + } + if (item.policies & OverlayableItem::Policy::kVendor) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION; + } + if (item.policies & OverlayableItem::Policy::kProduct) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; + } + if (item.policies & OverlayableItem::Policy::kSignature) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_SIGNATURE; } auto policy = overlayable_chunk->policy_ids.find(policy_flags); @@ -702,17 +710,15 @@ class PackageFlattener { } // namespace bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) { - if (options_.sort_stringpool_entries) { - // We must do this before writing the resources, since the string pool IDs may change. - table->string_pool.Prune(); - table->string_pool.Sort([](const StringPool::Context &a, const StringPool::Context &b) -> int { - int diff = util::compare(a.priority, b.priority); - if (diff == 0) { - diff = a.config.compare(b.config); - } - return diff; - }); - } + // We must do this before writing the resources, since the string pool IDs may change. + table->string_pool.Prune(); + table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int { + int diff = util::compare(a.priority, b.priority); + if (diff == 0) { + diff = a.config.compare(b.config); + } + return diff; + }); // Write the ResTable header. ChunkWriter table_writer(buffer_); diff --git a/tools/aapt2/format/binary/TableFlattener.h b/tools/aapt2/format/binary/TableFlattener.h index 71330e3fb74f..73c17295556b 100644 --- a/tools/aapt2/format/binary/TableFlattener.h +++ b/tools/aapt2/format/binary/TableFlattener.h @@ -44,9 +44,6 @@ struct TableFlattenerOptions { // Set of whitelisted resource names to avoid altering in key stringpool std::set<std::string> whitelisted_resources; - // When true, sort the entries in the values string pool by priority and configuration. - bool sort_stringpool_entries = true; - // Map from original resource paths to shortened resource paths. std::map<std::string, std::string> shortened_path_map; }; diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index ddc117399390..4c5dbec8ade8 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -671,9 +671,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { overlayable_item_two.policies |= OverlayableItem::Policy::kSystem; overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; - std::string name_three = "com.app.test:integer/overlayable_three_item"; - OverlayableItem overlayable_item_three(overlayable); - std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.test", 0x7f) @@ -683,8 +680,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { .SetOverlayable(name_one, overlayable_item_one) .AddSimple(name_two, ResourceId(0x7f020002)) .SetOverlayable(name_two, overlayable_item_two) - .AddSimple(name_three, ResourceId(0x7f020003)) - .SetOverlayable(name_three, overlayable_item_three) .Build(); ResourceTable output_table; @@ -713,16 +708,6 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem | OverlayableItem::Policy::kProduct | OverlayableItem::Policy::kVendor); - - search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); - ASSERT_TRUE(search_result); - ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable_item); - overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic); - EXPECT_EQ(overlayable_item.overlayable->name, "TestName"); - EXPECT_EQ(overlayable_item.overlayable->actor, "overlay://theme"); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic); } TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { @@ -745,6 +730,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { std::string name_three = "com.app.test:integer/overlayable_three"; OverlayableItem overlayable_item_three(group_one); + overlayable_item_three.policies |= OverlayableItem::Policy::kSignature; + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.test", 0x7f) @@ -793,7 +780,22 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); - EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic); + EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSignature); +} + +TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { + auto group = std::make_shared<Overlayable>("TestName", "overlay://theme"); + std::string name_zero = "com.app.test:integer/overlayable_zero"; + OverlayableItem overlayable_item_zero(group); + + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .SetPackageId("com.app.test", 0x7f) + .AddSimple(name_zero, ResourceId(0x7f020000)) + .SetOverlayable(name_zero, overlayable_item_zero) + .Build(); + ResourceTable output_table; + ASSERT_FALSE(Flatten(context_.get(), {}, table.get(), &output_table)); } } // namespace aapt diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index aff1b391f861..06f1bf74d7e7 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -390,6 +390,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, case pb::OverlayableItem::PRODUCT: out_overlayable->policies |= OverlayableItem::Policy::kProduct; break; + case pb::OverlayableItem::SIGNATURE: + out_overlayable->policies |= OverlayableItem::Policy::kSignature; + break; default: *out_error = "unknown overlayable policy"; return false; diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index b549e2369f98..eb2b1a2f35d3 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -309,6 +309,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item if (overlayable_item.policies & OverlayableItem::Policy::kVendor) { pb_overlayable_item->add_policy(pb::OverlayableItem::VENDOR); } + if (overlayable_item.policies & OverlayableItem::Policy::kSignature) { + pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE); + } SerializeSourceToPb(overlayable_item.source, source_pool, pb_overlayable_item->mutable_source()); diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index cce3939704cf..d369ac4c8816 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -526,6 +526,10 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { "FontPack", "overlay://theme")); overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic; + OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>( + "IconPack", "overlay://theme")); + overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature; + OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>( "Other", "overlay://customization")); overlayable_item_biz.comment ="comment"; @@ -536,6 +540,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { .SetOverlayable("com.app.a:bool/foo", overlayable_item_foo) .SetOverlayable("com.app.a:bool/bar", overlayable_item_bar) .SetOverlayable("com.app.a:bool/baz", overlayable_item_baz) + .SetOverlayable("com.app.a:bool/boz", overlayable_item_boz) .SetOverlayable("com.app.a:bool/biz", overlayable_item_biz) .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true")) .Build(); @@ -576,6 +581,14 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic)); + search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz")); + ASSERT_TRUE(search_result); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack")); + EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); + search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); ASSERT_TRUE(search_result); ASSERT_TRUE(search_result.value().entry->overlayable_item); diff --git a/tools/aapt2/integration-tests/Android.mk b/tools/aapt2/integration-tests/Android.mk deleted file mode 100644 index 6361f9b8ae7d..000000000000 --- a/tools/aapt2/integration-tests/Android.mk +++ /dev/null @@ -1,2 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp new file mode 100644 index 000000000000..79fb5734cd68 --- /dev/null +++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp @@ -0,0 +1,20 @@ +// +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "AaptAutoVersionTest", + sdk_version: "current", +} diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk deleted file mode 100644 index 03cce3534a4e..000000000000 --- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := AaptAutoVersionTest -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp new file mode 100644 index 000000000000..a94a01f12c9e --- /dev/null +++ b/tools/aapt2/integration-tests/BasicTest/Android.bp @@ -0,0 +1,20 @@ +// +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "AaptBasicTest", + sdk_version: "current", +} diff --git a/tools/aapt2/integration-tests/BasicTest/Android.mk b/tools/aapt2/integration-tests/BasicTest/Android.mk deleted file mode 100644 index d1605540371e..000000000000 --- a/tools/aapt2/integration-tests/BasicTest/Android.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := AaptBasicTest -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/StaticLibTest/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/Android.mk deleted file mode 100644 index 6361f9b8ae7d..000000000000 --- a/tools/aapt2/integration-tests/StaticLibTest/Android.mk +++ /dev/null @@ -1,2 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp new file mode 100644 index 000000000000..9aadff3d619e --- /dev/null +++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + + name: "AaptTestStaticLib_App", + sdk_version: "current", + srcs: ["src/**/*.java"], + asset_dirs: [ + "assets", + "assets2", + ], + static_libs: [ + "AaptTestStaticLib_LibOne", + "AaptTestStaticLib_LibTwo", + ], + aaptflags: [ + "--no-version-vectors", + "--no-version-transitions", + ], +} diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk deleted file mode 100644 index 3cce35de6a31..000000000000 --- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := AaptTestStaticLib_App -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2 -LOCAL_STATIC_ANDROID_LIBRARIES := \ - AaptTestStaticLib_LibOne \ - AaptTestStaticLib_LibTwo -LOCAL_AAPT_FLAGS := --no-version-vectors --no-version-transitions -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp new file mode 100644 index 000000000000..4c8181343a33 --- /dev/null +++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp @@ -0,0 +1,22 @@ +// +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_library { + name: "AaptTestStaticLib_LibOne", + sdk_version: "current", + srcs: ["src/**/*.java"], + resource_dirs: ["res"], +} diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk deleted file mode 100644 index da25f6477b08..000000000000 --- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestStaticLib_LibOne -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac. -LOCAL_JAR_EXCLUDE_FILES := none -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp new file mode 100644 index 000000000000..7c4f7ed90e69 --- /dev/null +++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp @@ -0,0 +1,23 @@ +// +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_library { + name: "AaptTestStaticLib_LibTwo", + sdk_version: "current", + srcs: ["src/**/*.java"], + resource_dirs: ["res"], + libs: ["AaptTestStaticLib_LibOne"], +} diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk deleted file mode 100644 index 27a3134e6ffa..000000000000 --- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (C) 2016 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_MODULE := AaptTestStaticLib_LibTwo -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLib_LibOne -include $(BUILD_STATIC_JAVA_LIBRARY) - diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp new file mode 100644 index 000000000000..68e6148e480c --- /dev/null +++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp @@ -0,0 +1,20 @@ +// +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "AaptSymlinkTest", + sdk_version: "current", +} diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk deleted file mode 100644 index 8da1141df7b3..000000000000 --- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_USE_AAPT2 := true -LOCAL_PACKAGE_NAME := AaptSymlinkTest -LOCAL_SDK_VERSION := current -LOCAL_MODULE_TAGS := tests -include $(BUILD_PACKAGE) diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp index 7b268bb283f4..604b2575daa1 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -251,6 +251,25 @@ bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_a return true; } +bool AppendSetArgsFromFile(const StringPiece& path, std::unordered_set<std::string>* out_argset, + std::string* out_error) { + std::string contents; + if(!ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) { + if (out_error) { + *out_error = "failed to read argument-list file"; + } + return false; + } + + for (StringPiece line : util::Tokenize(contents, ' ')) { + line = util::TrimWhitespace(line); + if (!line.empty()) { + out_argset->insert(line.to_string()); + } + } + return true; +} + bool FileFilter::SetPattern(const StringPiece& pattern) { pattern_tokens_ = util::SplitAndLowercase(pattern, ':'); return true; diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h index 58395526b193..481a4cdb6ad0 100644 --- a/tools/aapt2/util/Files.h +++ b/tools/aapt2/util/Files.h @@ -19,6 +19,7 @@ #include <memory> #include <string> +#include <unordered_set> #include <vector> #include "android-base/macros.h" @@ -86,6 +87,10 @@ Maybe<android::FileMap> MmapPath(const std::string& path, std::string* out_error bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist, std::string* out_error); +// Reads the file at path and appends each line to the outargset set. +bool AppendSetArgsFromFile(const android::StringPiece& path, + std::unordered_set<std::string>* out_argset, std::string* out_error); + // Filter that determines which resource files/directories are // processed by AAPT. Takes a pattern string supplied by the user. // Pattern format is specified in the FileFilter::SetPattern() method. |