Loading libs/androidfw/include/androidfw/ResourceTypes.h +21 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,7 @@ enum { RES_TABLE_OVERLAYABLE_TYPE = 0x0204, RES_TABLE_OVERLAYABLE_POLICY_TYPE = 0x0205, RES_TABLE_STAGED_ALIAS_TYPE = 0x0206, RES_TABLE_FLAGGED = 0x0207, }; /** Loading Loading @@ -1599,6 +1600,26 @@ union ResTable_sparseTypeEntry { static_assert(sizeof(ResTable_sparseTypeEntry) == sizeof(uint32_t), "ResTable_sparseTypeEntry must be 4 bytes in size"); /** * A container for other chunks all of whose values are behind a given flag. * * The flag_name_index is the index of the flag name in the value string pool. * * When the android runtime encounters this chunk it will check the flag against its current value. * If the flag is enabled and flag_negated is false or it is disabled and flag_negated is true, the * runtime will then process all of the chunks inside of it normally. Otherwise the entire chunk is * skipped. * * Currently this is chunk should be contained in a ResTable_typeSpec and contain any number of * ResTable_type. */ struct ResTable_flagged { struct ResChunk_header header; ResStringPool_ref flag_name_index; bool flag_negated; uint8_t padding[3]; }; struct ResTable_map_entry; Loading tools/aapt2/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -118,7 +118,7 @@ cc_library_host_static { "link/AutoVersioner.cpp", "link/FeatureFlagsFilter.cpp", "link/FlaggedXmlVersioner.cpp", "link/FlagDisabledResourceRemover.cpp", "link/FlagNotEnabledResourceRemover.cpp", "link/ManifestFixer.cpp", "link/NoDefaultResourceRemover.cpp", "link/PrivateAttributeMover.cpp", Loading tools/aapt2/Debug.cpp +56 −42 Original line number Diff line number Diff line Loading @@ -261,6 +261,34 @@ class ValueBodyPrinter : public ConstValueVisitor { } // namespace static void printResourceConfigValues(Printer* printer, bool show_sources, ConstValueVisitor* headline_printer, ConstValueVisitor* body_printer, const std::vector<const ResourceConfigValue*>& values) { for (const auto& value : values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); if (value->value->GetFlag()) { printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); } value->value->Accept(headline_printer); if (show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(body_printer); printer->Undent(); } } void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options, Printer* printer) { const auto table_view = table.GetPartitionedView(); Loading Loading @@ -335,50 +363,17 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& if (options.show_values) { printer->Indent(); for (const auto& value : entry.values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); if (value->value->GetFlag()) { printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); } value->value->Accept(&headline_printer); if (options.show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(&body_printer); printer->Undent(); } printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.values); if (!entry.flag_disabled_values.empty()) { printer->Println("Flag disabled values:"); for (const auto& value : entry.flag_disabled_values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); value->value->Accept(&headline_printer); if (options.show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(&body_printer); printer->Undent(); printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.flag_disabled_values); } if (!entry.readwrite_flag_values.empty()) { printer->Println("Read/write flag values:"); printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.readwrite_flag_values); } printer->Undent(); } Loading Loading @@ -663,6 +658,9 @@ class ChunkPrinter { case RES_TABLE_TYPE_SPEC_TYPE: printer_->Print("[RES_TABLE_TYPE_SPEC_TYPE]"); break; case RES_TABLE_FLAGGED: printer_->Print("[RES_TABLE_FLAGGED]"); break; default: break; } Loading Loading @@ -931,6 +929,18 @@ class ChunkPrinter { return success; } bool PrintFlagged(const ResTable_flagged* chunk) { const auto flag_name = android::util::GetString( value_pool_, android::util::DeviceToHost32(chunk->flag_name_index.index)); printer_->Print(StringPrintf(" name: %s", flag_name.c_str())); printer_->Print(StringPrintf(" negated: %s\n", chunk->flag_negated ? "true" : "false")); printer_->Indent(); bool success = PrintChunk( ResChunkPullParser(GetChunkData(&chunk->header), GetChunkDataLen(&chunk->header))); printer_->Undent(); return success; } bool PrintChunk(ResChunkPullParser&& parser) { while (ResChunkPullParser::IsGoodEvent(parser.Next())) { auto chunk = parser.chunk(); Loading Loading @@ -959,6 +969,10 @@ class ChunkPrinter { PrintTypeSpec(reinterpret_cast<const ResTable_typeSpec*>(chunk)); break; case RES_TABLE_FLAGGED: PrintFlagged(reinterpret_cast<const ResTable_flagged*>(chunk)); break; default: printer_->Print("\n"); break; Loading tools/aapt2/Resource.h +3 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ enum class ResourceType { kXml, }; enum class FlagStatus { NoFlag = 0, Disabled = 1, Enabled = 2 }; enum class FlagStatus { NoFlag = 0, Disabled = 1, Enabled = 2, RWFlag = 3 }; struct FeatureFlagAttribute { std::string name; Loading @@ -80,6 +80,8 @@ struct FeatureFlagAttribute { } bool operator==(const FeatureFlagAttribute& o) const = default; std::partial_ordering operator<=>(const FeatureFlagAttribute& o) const = default; }; android::StringPiece to_string(ResourceType type); Loading tools/aapt2/ResourceParser.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1547,6 +1547,11 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { std::string error; auto flag_status = GetFlagStatus(flag, options_.feature_flag_values, &error); if (flag_status) { if (flag_status == FlagStatus::RWFlag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Only read only flags may be used with styles: " + flag->name); return false; } value->SetFlagStatus(flag_status.value()); value->SetFlag(std::move(flag)); } else { Loading Loading @@ -1686,6 +1691,11 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser, std::string err; auto status = GetFlagStatus(flag, options_.feature_flag_values, &err); if (status) { if (status == FlagStatus::RWFlag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Only read only flags may be used with arrays: " + flag->name); return false; } item->SetFlagStatus(status.value()); } else { diag_->Error(android::DiagMessage(item_source) << err); Loading Loading
libs/androidfw/include/androidfw/ResourceTypes.h +21 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,7 @@ enum { RES_TABLE_OVERLAYABLE_TYPE = 0x0204, RES_TABLE_OVERLAYABLE_POLICY_TYPE = 0x0205, RES_TABLE_STAGED_ALIAS_TYPE = 0x0206, RES_TABLE_FLAGGED = 0x0207, }; /** Loading Loading @@ -1599,6 +1600,26 @@ union ResTable_sparseTypeEntry { static_assert(sizeof(ResTable_sparseTypeEntry) == sizeof(uint32_t), "ResTable_sparseTypeEntry must be 4 bytes in size"); /** * A container for other chunks all of whose values are behind a given flag. * * The flag_name_index is the index of the flag name in the value string pool. * * When the android runtime encounters this chunk it will check the flag against its current value. * If the flag is enabled and flag_negated is false or it is disabled and flag_negated is true, the * runtime will then process all of the chunks inside of it normally. Otherwise the entire chunk is * skipped. * * Currently this is chunk should be contained in a ResTable_typeSpec and contain any number of * ResTable_type. */ struct ResTable_flagged { struct ResChunk_header header; ResStringPool_ref flag_name_index; bool flag_negated; uint8_t padding[3]; }; struct ResTable_map_entry; Loading
tools/aapt2/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -118,7 +118,7 @@ cc_library_host_static { "link/AutoVersioner.cpp", "link/FeatureFlagsFilter.cpp", "link/FlaggedXmlVersioner.cpp", "link/FlagDisabledResourceRemover.cpp", "link/FlagNotEnabledResourceRemover.cpp", "link/ManifestFixer.cpp", "link/NoDefaultResourceRemover.cpp", "link/PrivateAttributeMover.cpp", Loading
tools/aapt2/Debug.cpp +56 −42 Original line number Diff line number Diff line Loading @@ -261,6 +261,34 @@ class ValueBodyPrinter : public ConstValueVisitor { } // namespace static void printResourceConfigValues(Printer* printer, bool show_sources, ConstValueVisitor* headline_printer, ConstValueVisitor* body_printer, const std::vector<const ResourceConfigValue*>& values) { for (const auto& value : values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); if (value->value->GetFlag()) { printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); } value->value->Accept(headline_printer); if (show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(body_printer); printer->Undent(); } } void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options, Printer* printer) { const auto table_view = table.GetPartitionedView(); Loading Loading @@ -335,50 +363,17 @@ void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& if (options.show_values) { printer->Indent(); for (const auto& value : entry.values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); if (value->value->GetFlag()) { printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); } value->value->Accept(&headline_printer); if (options.show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(&body_printer); printer->Undent(); } printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.values); if (!entry.flag_disabled_values.empty()) { printer->Println("Flag disabled values:"); for (const auto& value : entry.flag_disabled_values) { printer->Print("("); printer->Print(value->config.to_string()); printer->Print(") "); printer->Print("(featureFlag="); if (value->value->GetFlag()->negated) { printer->Print("!"); } printer->Print(value->value->GetFlag()->name); printer->Print(") "); value->value->Accept(&headline_printer); if (options.show_sources && !value->value->GetSource().path.empty()) { printer->Print(" src="); printer->Print(value->value->GetSource().to_string()); } printer->Println(); printer->Indent(); value->value->Accept(&body_printer); printer->Undent(); printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.flag_disabled_values); } if (!entry.readwrite_flag_values.empty()) { printer->Println("Read/write flag values:"); printResourceConfigValues(printer, options.show_sources, &headline_printer, &body_printer, entry.readwrite_flag_values); } printer->Undent(); } Loading Loading @@ -663,6 +658,9 @@ class ChunkPrinter { case RES_TABLE_TYPE_SPEC_TYPE: printer_->Print("[RES_TABLE_TYPE_SPEC_TYPE]"); break; case RES_TABLE_FLAGGED: printer_->Print("[RES_TABLE_FLAGGED]"); break; default: break; } Loading Loading @@ -931,6 +929,18 @@ class ChunkPrinter { return success; } bool PrintFlagged(const ResTable_flagged* chunk) { const auto flag_name = android::util::GetString( value_pool_, android::util::DeviceToHost32(chunk->flag_name_index.index)); printer_->Print(StringPrintf(" name: %s", flag_name.c_str())); printer_->Print(StringPrintf(" negated: %s\n", chunk->flag_negated ? "true" : "false")); printer_->Indent(); bool success = PrintChunk( ResChunkPullParser(GetChunkData(&chunk->header), GetChunkDataLen(&chunk->header))); printer_->Undent(); return success; } bool PrintChunk(ResChunkPullParser&& parser) { while (ResChunkPullParser::IsGoodEvent(parser.Next())) { auto chunk = parser.chunk(); Loading Loading @@ -959,6 +969,10 @@ class ChunkPrinter { PrintTypeSpec(reinterpret_cast<const ResTable_typeSpec*>(chunk)); break; case RES_TABLE_FLAGGED: PrintFlagged(reinterpret_cast<const ResTable_flagged*>(chunk)); break; default: printer_->Print("\n"); break; Loading
tools/aapt2/Resource.h +3 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ enum class ResourceType { kXml, }; enum class FlagStatus { NoFlag = 0, Disabled = 1, Enabled = 2 }; enum class FlagStatus { NoFlag = 0, Disabled = 1, Enabled = 2, RWFlag = 3 }; struct FeatureFlagAttribute { std::string name; Loading @@ -80,6 +80,8 @@ struct FeatureFlagAttribute { } bool operator==(const FeatureFlagAttribute& o) const = default; std::partial_ordering operator<=>(const FeatureFlagAttribute& o) const = default; }; android::StringPiece to_string(ResourceType type); Loading
tools/aapt2/ResourceParser.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -1547,6 +1547,11 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { std::string error; auto flag_status = GetFlagStatus(flag, options_.feature_flag_values, &error); if (flag_status) { if (flag_status == FlagStatus::RWFlag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Only read only flags may be used with styles: " + flag->name); return false; } value->SetFlagStatus(flag_status.value()); value->SetFlag(std::move(flag)); } else { Loading Loading @@ -1686,6 +1691,11 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser, std::string err; auto status = GetFlagStatus(flag, options_.feature_flag_values, &err); if (status) { if (status == FlagStatus::RWFlag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Only read only flags may be used with arrays: " + flag->name); return false; } item->SetFlagStatus(status.value()); } else { diag_->Error(android::DiagMessage(item_source) << err); Loading