summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt2/Debug.cpp2
-rw-r--r--tools/aapt2/ResourceParser.cpp18
-rw-r--r--tools/aapt2/ResourceParser_test.cpp48
-rw-r--r--tools/aapt2/ResourceTable.h3
-rw-r--r--tools/aapt2/ResourceUtils.cpp4
-rw-r--r--tools/aapt2/Resources.proto14
-rw-r--r--tools/aapt2/StringPool.cpp22
-rw-r--r--tools/aapt2/StringPool.h6
-rw-r--r--tools/aapt2/StringPool_test.cpp18
-rw-r--r--tools/aapt2/cmd/Convert.cpp17
-rw-r--r--tools/aapt2/cmd/Link.cpp32
-rw-r--r--tools/aapt2/cmd/Link.h9
-rw-r--r--tools/aapt2/cmd/Util.cpp7
-rw-r--r--tools/aapt2/cmd/Util.h5
-rw-r--r--tools/aapt2/cmd/Util_test.cpp8
-rw-r--r--tools/aapt2/format/binary/BinaryResourceParser.cpp7
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp60
-rw-r--r--tools/aapt2/format/binary/TableFlattener.h3
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp34
-rw-r--r--tools/aapt2/format/proto/ProtoDeserialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize_test.cpp13
-rw-r--r--tools/aapt2/integration-tests/Android.mk2
-rw-r--r--tools/aapt2/integration-tests/AutoVersionTest/Android.bp20
-rw-r--r--tools/aapt2/integration-tests/AutoVersionTest/Android.mk24
-rw-r--r--tools/aapt2/integration-tests/BasicTest/Android.bp20
-rw-r--r--tools/aapt2/integration-tests/BasicTest/Android.mk24
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/Android.mk2
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/App/Android.bp34
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/App/Android.mk30
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp22
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk29
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp23
-rw-r--r--tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk28
-rw-r--r--tools/aapt2/integration-tests/SymlinkTest/Android.bp20
-rw-r--r--tools/aapt2/integration-tests/SymlinkTest/Android.mk24
-rw-r--r--tools/aapt2/util/Files.cpp19
-rw-r--r--tools/aapt2/util/Files.h5
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.