Add odm and oem policies
This change adds parsing, encoding, and validating of odm and oem
overlayable policies to aapt2, libandroidfw, and idmap2.
Bug: 121033532
Test: aapt2_tests, idmap2_tests
Change-Id: Ifc0d4b6c9f9c37e06b2988abade69dbb277c50c2
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 5e8d870..fe401e2 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1143,34 +1143,38 @@
} else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
// Parse the polices separated by vertical bar characters to allow for specifying multiple
// policies. Items within the policy tag will have the specified policy.
- for (StringPiece part : util::Tokenize(maybe_type.value(), '|')) {
+ static const auto kPolicyMap =
+ ImmutableMap<StringPiece, OverlayableItem::Policy>::CreatePreSorted({
+ {"odm", OverlayableItem::Policy::kOdm},
+ {"oem", OverlayableItem::Policy::kOem},
+ {"product", OverlayableItem::Policy::kProduct},
+ {"public", OverlayableItem::Policy::kPublic},
+ {"signature", OverlayableItem::Policy::kSignature},
+ {"system", OverlayableItem::Policy::kSystem},
+ {"vendor", OverlayableItem::Policy::kVendor},
+ });
+
+ for (const StringPiece& part : util::Tokenize(maybe_type.value(), '|')) {
StringPiece trimmed_part = util::TrimWhitespace(part);
- if (trimmed_part == "public") {
- current_policies |= OverlayableItem::Policy::kPublic;
- } else if (trimmed_part == "product") {
- current_policies |= OverlayableItem::Policy::kProduct;
- } else if (trimmed_part == "system") {
- 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 {
+ const auto policy = kPolicyMap.find(trimmed_part);
+ if (policy == kPolicyMap.end()) {
diag_->Error(DiagMessage(element_source)
<< "<policy> has unsupported type '" << trimmed_part << "'");
error = true;
continue;
}
+
+ current_policies |= policy->second;
}
} else {
diag_->Error(DiagMessage(element_source)
- << "<policy> must have a 'type' attribute");
+ << "<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 << "> "
- << " in <overlayable>");
+ << " in <overlayable>");
error = true;
break;
}
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 8577921..7c8b6d0 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -971,6 +971,12 @@
<policy type="signature">
<item type="string" name="foz" />
</policy>
+ <policy type="odm">
+ <item type="string" name="biz" />
+ </policy>
+ <policy type="oem">
+ <item type="string" name="buz" />
+ </policy>
</overlayable>)";
ASSERT_TRUE(TestParse(input));
@@ -1013,6 +1019,22 @@
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));
+
+ search_result = table_.FindResource(test::ParseNameOrDie("string/biz"));
+ 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::kOdm));
+
+ search_result = table_.FindResource(test::ParseNameOrDie("string/buz"));
+ 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::kOem));
}
TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) {
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 7ed7897..30ba1ae 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -79,22 +79,28 @@
// Represents the types overlays that are allowed to overlay the resource.
typedef uint32_t PolicyFlags;
enum Policy : uint32_t {
- kNone = 0x00,
+ kNone = 0x00000000,
// The resource can be overlaid by any overlay.
- kPublic = 0x01,
+ kPublic = 0x00000001,
// The resource can be overlaid by any overlay on the system partition.
- kSystem = 0x02,
+ kSystem = 0x00000002,
// The resource can be overlaid by any overlay on the vendor partition.
- kVendor = 0x04,
+ kVendor = 0x00000004,
// The resource can be overlaid by any overlay on the product partition.
- kProduct = 0x08,
+ kProduct = 0x00000008,
// The resource can be overlaid by any overlay signed with the same signature as its actor.
- kSignature = 0x010,
+ kSignature = 0x00000010,
+
+ // The resource can be overlaid by any overlay on the odm partition.
+ kOdm = 0x00000020,
+
+ // The resource can be overlaid by any overlay on the oem partition.
+ kOem = 0x00000040,
};
std::shared_ptr<Overlayable> overlayable;
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index a2fd7c6..12cf65b 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -157,6 +157,8 @@
VENDOR = 3;
PRODUCT = 4;
SIGNATURE = 5;
+ ODM = 6;
+ OEM = 7;
}
// The location of the <item> declaration in source.
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 59eb9ec2..fd8e36e 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -475,6 +475,14 @@
& ResTable_overlayable_policy_header::POLICY_SIGNATURE) {
policies |= OverlayableItem::Policy::kSignature;
}
+ if (policy_header->policy_flags
+ & ResTable_overlayable_policy_header::POLICY_ODM_PARTITION) {
+ policies |= OverlayableItem::Policy::kOdm;
+ }
+ if (policy_header->policy_flags
+ & ResTable_overlayable_policy_header::POLICY_OEM_PARTITION) {
+ policies |= OverlayableItem::Policy::kOem;
+ }
const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>(
((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize));
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index aa578a2..f2e72da 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -496,6 +496,12 @@
if (item.policies & OverlayableItem::Policy::kSignature) {
policy_flags |= ResTable_overlayable_policy_header::POLICY_SIGNATURE;
}
+ if (item.policies & OverlayableItem::Policy::kOdm) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_ODM_PARTITION;
+ }
+ if (item.policies & OverlayableItem::Policy::kOem) {
+ policy_flags |= ResTable_overlayable_policy_header::POLICY_OEM_PARTITION;
+ }
auto policy = overlayable_chunk->policy_ids.find(policy_flags);
if (policy != overlayable_chunk->policy_ids.end()) {
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index 4c5dbec..a940923 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -724,8 +724,8 @@
std::string name_two = "com.app.test:integer/overlayable_two";
OverlayableItem overlayable_item_two(group);
- overlayable_item_two.policies |= OverlayableItem::Policy::kProduct;
- overlayable_item_two.policies |= OverlayableItem::Policy::kSystem;
+ overlayable_item_two.policies |= OverlayableItem::Policy::kOdm;
+ overlayable_item_two.policies |= OverlayableItem::Policy::kOem;
overlayable_item_two.policies |= OverlayableItem::Policy::kVendor;
std::string name_three = "com.app.test:integer/overlayable_three";
@@ -744,6 +744,7 @@
.AddSimple(name_three, ResourceId(0x7f020003))
.SetOverlayable(name_three, overlayable_item_three)
.Build();
+
ResourceTable output_table;
ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &output_table));
auto search_result = output_table.FindResource(test::ParseNameOrDie(name_zero));
@@ -755,6 +756,7 @@
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
| OverlayableItem::Policy::kProduct);
+
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -763,6 +765,7 @@
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
+
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -770,9 +773,10 @@
result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
- EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
- | OverlayableItem::Policy::kProduct
+ EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kOdm
+ | OverlayableItem::Policy::kOem
| OverlayableItem::Policy::kVendor);
+
search_result = output_table.FindResource(test::ParseNameOrDie(name_three));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 06f1bf7..bb21c1c 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -393,6 +393,12 @@
case pb::OverlayableItem::SIGNATURE:
out_overlayable->policies |= OverlayableItem::Policy::kSignature;
break;
+ case pb::OverlayableItem::ODM:
+ out_overlayable->policies |= OverlayableItem::Policy::kOdm;
+ break;
+ case pb::OverlayableItem::OEM:
+ out_overlayable->policies |= OverlayableItem::Policy::kOem;
+ 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 eb2b1a2..58e1e6e 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -312,6 +312,12 @@
if (overlayable_item.policies & OverlayableItem::Policy::kSignature) {
pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE);
}
+ if (overlayable_item.policies & OverlayableItem::Policy::kOdm) {
+ pb_overlayable_item->add_policy(pb::OverlayableItem::ODM);
+ }
+ if (overlayable_item.policies & OverlayableItem::Policy::kOem) {
+ pb_overlayable_item->add_policy(pb::OverlayableItem::OEM);
+ }
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 d369ac4..f252f33 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -529,6 +529,8 @@
OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>(
"IconPack", "overlay://theme"));
overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature;
+ overlayable_item_boz.policies |= OverlayableItem::Policy::kOdm;
+ overlayable_item_boz.policies |= OverlayableItem::Policy::kOem;
OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>(
"Other", "overlay://customization"));
@@ -587,7 +589,9 @@
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));
+ EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature
+ | OverlayableItem::Policy::kOdm
+ | OverlayableItem::Policy::kOem));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
ASSERT_TRUE(search_result);