Loading libs/androidfw/include/androidfw/ResourceTypes.h +6 −2 Original line number Diff line number Diff line Loading @@ -1339,9 +1339,13 @@ struct ResTable_typeSpec // Number of uint32_t entry configuration masks that follow. uint32_t entryCount; enum { enum : uint32_t { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000 SPEC_PUBLIC = 0x40000000u, // Additional flag indicating an entry is overlayable at runtime. // Added in Android-P. SPEC_OVERLAYABLE = 0x80000000u, }; }; Loading tools/aapt2/Debug.cpp +23 −17 Original line number Diff line number Diff line Loading @@ -294,20 +294,25 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& printer->Print("/"); printer->Print(entry->name); switch (entry->symbol_status.state) { case SymbolState::kPublic: switch (entry->visibility.level) { case Visibility::Level::kPublic: printer->Print(" PUBLIC"); break; case SymbolState::kPrivate: case Visibility::Level::kPrivate: printer->Print(" _PRIVATE_"); break; case SymbolState::kUndefined: case Visibility::Level::kUndefined: // Print nothing. break; } if (entry->overlayable) { printer->Print(" OVERLAYABLE"); } printer->Println(); if (options.show_values) { printer->Indent(); for (const auto& value : entry->values) { printer->Print("("); Loading @@ -325,6 +330,7 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& } printer->Undent(); } } printer->Undent(); } printer->Undent(); Loading tools/aapt2/Debug.h +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ namespace aapt { struct DebugPrintTableOptions { bool show_sources = false; bool show_values = true; }; struct Debug { Loading tools/aapt2/ResourceParser.cpp +47 −27 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include "util/Util.h" #include "xml/XmlPullParser.h" using android::StringPiece; using ::android::StringPiece; namespace aapt { Loading Loading @@ -90,9 +90,12 @@ struct ParsedResource { ConfigDescription config; std::string product; Source source; ResourceId id; Maybe<SymbolState> symbol_state; Visibility::Level visibility_level = Visibility::Level::kUndefined; bool allow_new = false; bool overlayable = false; std::string comment; std::unique_ptr<Value> value; std::list<ParsedResource> child_resources; Loading @@ -106,24 +109,41 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed res->comment = trimmed_comment.to_string(); } if (res->symbol_state) { Symbol symbol; symbol.state = res->symbol_state.value(); symbol.source = res->source; symbol.comment = res->comment; symbol.allow_new = res->allow_new; if (!table->SetSymbolState(res->name, res->id, symbol, diag)) { if (res->visibility_level != Visibility::Level::kUndefined) { Visibility visibility; visibility.level = res->visibility_level; visibility.source = res->source; visibility.comment = res->comment; if (!table->SetVisibilityWithId(res->name, visibility, res->id, diag)) { return false; } } if (res->allow_new) { AllowNew allow_new; allow_new.source = res->source; allow_new.comment = res->comment; if (!table->SetAllowNew(res->name, allow_new, diag)) { return false; } } if (res->overlayable) { Overlayable overlayable; overlayable.source = res->source; overlayable.comment = res->comment; if (!table->SetOverlayable(res->name, overlayable, diag)) { return false; } } if (res->value) { if (res->value != nullptr) { // Attach the comment, source and config to the value. res->value->SetComment(std::move(res->comment)); res->value->SetSource(std::move(res->source)); if (!table->AddResource(res->name, res->id, res->config, res->product, std::move(res->value), diag)) { if (!table->AddResourceWithId(res->name, res->id, res->config, res->product, std::move(res->value), diag)) { return false; } } Loading Loading @@ -601,8 +621,7 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser, // Process the raw value. std::unique_ptr<Item> processed_item = ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference); ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference); if (processed_item) { // Fix up the reference. if (Reference* ref = ValueCast<Reference>(processed_item.get())) { Loading Loading @@ -689,8 +708,7 @@ bool ResourceParser::ParseString(xml::XmlPullParser* parser, return true; } bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) { bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (out_resource->config != ConfigDescription::DefaultConfig()) { diag_->Warn(DiagMessage(out_resource->source) << "ignoring configuration '" << out_resource->config << "' for <public> tag"); Loading Loading @@ -728,7 +746,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, out_resource->value = util::make_unique<Id>(); } out_resource->symbol_state = SymbolState::kPublic; out_resource->visibility_level = Visibility::Level::kPublic; return true; } Loading Loading @@ -818,7 +836,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource child_resource.id = next_id; child_resource.comment = std::move(comment); child_resource.source = item_source; child_resource.symbol_state = SymbolState::kPublic; child_resource.visibility_level = Visibility::Level::kPublic; out_resource->child_resources.push_back(std::move(child_resource)); next_id.id += 1; Loading Loading @@ -864,7 +882,7 @@ bool ResourceParser::ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out return false; } out_resource->symbol_state = SymbolState::kPrivate; out_resource->visibility_level = Visibility::Level::kPrivate; return true; } Loading Loading @@ -920,8 +938,12 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource continue; } // TODO(b/64980941): Mark the symbol as overlayable and allow marking which entity can overlay // the resource (system/app). ParsedResource child_resource; child_resource.name.type = *type; child_resource.name.entry = maybe_name.value().to_string(); child_resource.source = item_source; child_resource.overlayable = true; out_resource->child_resources.push_back(std::move(child_resource)); xml::XmlPullParser::SkipCurrentElement(parser); } else if (!ShouldIgnoreElement(element_namespace, element_name)) { Loading @@ -932,10 +954,9 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource return !error; } bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) { bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (ParseSymbolImpl(parser, out_resource)) { out_resource->symbol_state = SymbolState::kUndefined; out_resource->visibility_level = Visibility::Level::kUndefined; out_resource->allow_new = true; return true; } Loading Loading @@ -1395,9 +1416,8 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource) { out_resource->name.type = ResourceType::kStyleable; // Declare-styleable is kPrivate by default, because it technically only // exists in R.java. out_resource->symbol_state = SymbolState::kPublic; // Declare-styleable is kPrivate by default, because it technically only exists in R.java. out_resource->visibility_level = Visibility::Level::kPublic; // Declare-styleable only ends up in default config; if (out_resource->config != ConfigDescription::DefaultConfig()) { Loading tools/aapt2/ResourceParser_test.cpp +41 −4 Original line number Diff line number Diff line Loading @@ -29,8 +29,8 @@ using ::aapt::io::StringInputStream; using ::aapt::test::StrValueEq; using ::aapt::test::ValueEq; using ::android::ResTable_map; using ::android::Res_value; using ::android::ResTable_map; using ::android::StringPiece; using ::testing::Eq; using ::testing::IsEmpty; Loading @@ -38,6 +38,7 @@ using ::testing::IsNull; using ::testing::NotNull; using ::testing::Pointee; using ::testing::SizeIs; using ::testing::StrEq; namespace aapt { Loading Loading @@ -482,7 +483,7 @@ TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("styleable/foo")); ASSERT_TRUE(result); EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kPublic)); EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic)); Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); ASSERT_THAT(attr, NotNull()); Loading Loading @@ -718,6 +719,26 @@ TEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041))); } TEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) { std::string input = R"( <!-- private --> <java-symbol type="string" name="foo" /> <!-- public --> <public type="string" name="foo" id="0x01020000" /> <!-- private2 --> <java-symbol type="string" name="foo" />)"; ASSERT_TRUE(TestParse(input)); Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("string/foo")); ASSERT_TRUE(result); ResourceEntry* entry = result.value().entry; ASSERT_THAT(entry, NotNull()); EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kPublic)); EXPECT_THAT(entry->visibility.comment, StrEq("public")); } TEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { ASSERT_TRUE(TestParse(R"(<item type="layout" name="foo">@layout/bar</item>)")); ASSERT_FALSE(TestParse(R"(<item type="layout" name="bar">"this is a string"</item>)")); Loading @@ -731,8 +752,8 @@ TEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) ASSERT_TRUE(result); const ResourceEntry* entry = result.value().entry; ASSERT_THAT(entry, NotNull()); EXPECT_THAT(entry->symbol_status.state, Eq(SymbolState::kUndefined)); EXPECT_TRUE(entry->symbol_status.allow_new); EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kUndefined)); EXPECT_TRUE(entry->allow_new); } TEST_F(ResourceParserTest, ParseItemElementWithFormat) { Loading Loading @@ -833,6 +854,22 @@ TEST_F(ResourceParserTest, ParseOverlayableTagWithSystemPolicy) { <item type="string" name="bar" /> </overlayable>)"; ASSERT_TRUE(TestParse(input)); Maybe<ResourceTable::SearchResult> search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined)); EXPECT_TRUE(search_result.value().entry->overlayable); } TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { std::string input = R"( <overlayable> <item type="string" name="foo" /> <item type="string" name="foo" /> </overlayable>)"; EXPECT_FALSE(TestParse(input)); } } // namespace aapt Loading
libs/androidfw/include/androidfw/ResourceTypes.h +6 −2 Original line number Diff line number Diff line Loading @@ -1339,9 +1339,13 @@ struct ResTable_typeSpec // Number of uint32_t entry configuration masks that follow. uint32_t entryCount; enum { enum : uint32_t { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000 SPEC_PUBLIC = 0x40000000u, // Additional flag indicating an entry is overlayable at runtime. // Added in Android-P. SPEC_OVERLAYABLE = 0x80000000u, }; }; Loading
tools/aapt2/Debug.cpp +23 −17 Original line number Diff line number Diff line Loading @@ -294,20 +294,25 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& printer->Print("/"); printer->Print(entry->name); switch (entry->symbol_status.state) { case SymbolState::kPublic: switch (entry->visibility.level) { case Visibility::Level::kPublic: printer->Print(" PUBLIC"); break; case SymbolState::kPrivate: case Visibility::Level::kPrivate: printer->Print(" _PRIVATE_"); break; case SymbolState::kUndefined: case Visibility::Level::kUndefined: // Print nothing. break; } if (entry->overlayable) { printer->Print(" OVERLAYABLE"); } printer->Println(); if (options.show_values) { printer->Indent(); for (const auto& value : entry->values) { printer->Print("("); Loading @@ -325,6 +330,7 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& } printer->Undent(); } } printer->Undent(); } printer->Undent(); Loading
tools/aapt2/Debug.h +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ namespace aapt { struct DebugPrintTableOptions { bool show_sources = false; bool show_values = true; }; struct Debug { Loading
tools/aapt2/ResourceParser.cpp +47 −27 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include "util/Util.h" #include "xml/XmlPullParser.h" using android::StringPiece; using ::android::StringPiece; namespace aapt { Loading Loading @@ -90,9 +90,12 @@ struct ParsedResource { ConfigDescription config; std::string product; Source source; ResourceId id; Maybe<SymbolState> symbol_state; Visibility::Level visibility_level = Visibility::Level::kUndefined; bool allow_new = false; bool overlayable = false; std::string comment; std::unique_ptr<Value> value; std::list<ParsedResource> child_resources; Loading @@ -106,24 +109,41 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed res->comment = trimmed_comment.to_string(); } if (res->symbol_state) { Symbol symbol; symbol.state = res->symbol_state.value(); symbol.source = res->source; symbol.comment = res->comment; symbol.allow_new = res->allow_new; if (!table->SetSymbolState(res->name, res->id, symbol, diag)) { if (res->visibility_level != Visibility::Level::kUndefined) { Visibility visibility; visibility.level = res->visibility_level; visibility.source = res->source; visibility.comment = res->comment; if (!table->SetVisibilityWithId(res->name, visibility, res->id, diag)) { return false; } } if (res->allow_new) { AllowNew allow_new; allow_new.source = res->source; allow_new.comment = res->comment; if (!table->SetAllowNew(res->name, allow_new, diag)) { return false; } } if (res->overlayable) { Overlayable overlayable; overlayable.source = res->source; overlayable.comment = res->comment; if (!table->SetOverlayable(res->name, overlayable, diag)) { return false; } } if (res->value) { if (res->value != nullptr) { // Attach the comment, source and config to the value. res->value->SetComment(std::move(res->comment)); res->value->SetSource(std::move(res->source)); if (!table->AddResource(res->name, res->id, res->config, res->product, std::move(res->value), diag)) { if (!table->AddResourceWithId(res->name, res->id, res->config, res->product, std::move(res->value), diag)) { return false; } } Loading Loading @@ -601,8 +621,7 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser, // Process the raw value. std::unique_ptr<Item> processed_item = ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference); ResourceUtils::TryParseItemForAttribute(raw_value, type_mask, on_create_reference); if (processed_item) { // Fix up the reference. if (Reference* ref = ValueCast<Reference>(processed_item.get())) { Loading Loading @@ -689,8 +708,7 @@ bool ResourceParser::ParseString(xml::XmlPullParser* parser, return true; } bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) { bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (out_resource->config != ConfigDescription::DefaultConfig()) { diag_->Warn(DiagMessage(out_resource->source) << "ignoring configuration '" << out_resource->config << "' for <public> tag"); Loading Loading @@ -728,7 +746,7 @@ bool ResourceParser::ParsePublic(xml::XmlPullParser* parser, out_resource->value = util::make_unique<Id>(); } out_resource->symbol_state = SymbolState::kPublic; out_resource->visibility_level = Visibility::Level::kPublic; return true; } Loading Loading @@ -818,7 +836,7 @@ bool ResourceParser::ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource child_resource.id = next_id; child_resource.comment = std::move(comment); child_resource.source = item_source; child_resource.symbol_state = SymbolState::kPublic; child_resource.visibility_level = Visibility::Level::kPublic; out_resource->child_resources.push_back(std::move(child_resource)); next_id.id += 1; Loading Loading @@ -864,7 +882,7 @@ bool ResourceParser::ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out return false; } out_resource->symbol_state = SymbolState::kPrivate; out_resource->visibility_level = Visibility::Level::kPrivate; return true; } Loading Loading @@ -920,8 +938,12 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource continue; } // TODO(b/64980941): Mark the symbol as overlayable and allow marking which entity can overlay // the resource (system/app). ParsedResource child_resource; child_resource.name.type = *type; child_resource.name.entry = maybe_name.value().to_string(); child_resource.source = item_source; child_resource.overlayable = true; out_resource->child_resources.push_back(std::move(child_resource)); xml::XmlPullParser::SkipCurrentElement(parser); } else if (!ShouldIgnoreElement(element_namespace, element_name)) { Loading @@ -932,10 +954,9 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource return !error; } bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) { bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (ParseSymbolImpl(parser, out_resource)) { out_resource->symbol_state = SymbolState::kUndefined; out_resource->visibility_level = Visibility::Level::kUndefined; out_resource->allow_new = true; return true; } Loading Loading @@ -1395,9 +1416,8 @@ bool ResourceParser::ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource) { out_resource->name.type = ResourceType::kStyleable; // Declare-styleable is kPrivate by default, because it technically only // exists in R.java. out_resource->symbol_state = SymbolState::kPublic; // Declare-styleable is kPrivate by default, because it technically only exists in R.java. out_resource->visibility_level = Visibility::Level::kPublic; // Declare-styleable only ends up in default config; if (out_resource->config != ConfigDescription::DefaultConfig()) { Loading
tools/aapt2/ResourceParser_test.cpp +41 −4 Original line number Diff line number Diff line Loading @@ -29,8 +29,8 @@ using ::aapt::io::StringInputStream; using ::aapt::test::StrValueEq; using ::aapt::test::ValueEq; using ::android::ResTable_map; using ::android::Res_value; using ::android::ResTable_map; using ::android::StringPiece; using ::testing::Eq; using ::testing::IsEmpty; Loading @@ -38,6 +38,7 @@ using ::testing::IsNull; using ::testing::NotNull; using ::testing::Pointee; using ::testing::SizeIs; using ::testing::StrEq; namespace aapt { Loading Loading @@ -482,7 +483,7 @@ TEST_F(ResourceParserTest, ParseAttributesDeclareStyleable) { Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("styleable/foo")); ASSERT_TRUE(result); EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kPublic)); EXPECT_THAT(result.value().entry->visibility.level, Eq(Visibility::Level::kPublic)); Attribute* attr = test::GetValue<Attribute>(&table_, "attr/bar"); ASSERT_THAT(attr, NotNull()); Loading Loading @@ -718,6 +719,26 @@ TEST_F(ResourceParserTest, AutoIncrementIdsInPublicGroup) { EXPECT_THAT(actual_id, Eq(ResourceId(0x01010041))); } TEST_F(ResourceParserTest, StrongestSymbolVisibilityWins) { std::string input = R"( <!-- private --> <java-symbol type="string" name="foo" /> <!-- public --> <public type="string" name="foo" id="0x01020000" /> <!-- private2 --> <java-symbol type="string" name="foo" />)"; ASSERT_TRUE(TestParse(input)); Maybe<ResourceTable::SearchResult> result = table_.FindResource(test::ParseNameOrDie("string/foo")); ASSERT_TRUE(result); ResourceEntry* entry = result.value().entry; ASSERT_THAT(entry, NotNull()); EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kPublic)); EXPECT_THAT(entry->visibility.comment, StrEq("public")); } TEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) { ASSERT_TRUE(TestParse(R"(<item type="layout" name="foo">@layout/bar</item>)")); ASSERT_FALSE(TestParse(R"(<item type="layout" name="bar">"this is a string"</item>)")); Loading @@ -731,8 +752,8 @@ TEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) ASSERT_TRUE(result); const ResourceEntry* entry = result.value().entry; ASSERT_THAT(entry, NotNull()); EXPECT_THAT(entry->symbol_status.state, Eq(SymbolState::kUndefined)); EXPECT_TRUE(entry->symbol_status.allow_new); EXPECT_THAT(entry->visibility.level, Eq(Visibility::Level::kUndefined)); EXPECT_TRUE(entry->allow_new); } TEST_F(ResourceParserTest, ParseItemElementWithFormat) { Loading Loading @@ -833,6 +854,22 @@ TEST_F(ResourceParserTest, ParseOverlayableTagWithSystemPolicy) { <item type="string" name="bar" /> </overlayable>)"; ASSERT_TRUE(TestParse(input)); Maybe<ResourceTable::SearchResult> search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined)); EXPECT_TRUE(search_result.value().entry->overlayable); } TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { std::string input = R"( <overlayable> <item type="string" name="foo" /> <item type="string" name="foo" /> </overlayable>)"; EXPECT_FALSE(TestParse(input)); } } // namespace aapt