Loading core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.FileUtils; import android.util.DisplayMetrics; import android.view.LayoutInflater; Loading Loading @@ -151,6 +152,27 @@ public class ResourceFlaggingTest { mResources.getDrawable(R.drawable.removedpng); } @Test public void testDisabledStyleDoesntOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style1, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } @Test public void testEnabledStyleDoesOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style2, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } @Test public void testEnabledStyleItemDoesOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style3, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } private LayoutInflater getLayoutInflater() { ContextWrapper c = new ContextWrapper(mContext) { private LayoutInflater mInflater; Loading tools/aapt2/ResourceParser.cpp +22 −1 Original line number Diff line number Diff line Loading @@ -1529,13 +1529,34 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { ResolvePackage(parser, &maybe_key.value()); maybe_key.value().SetSource(source); auto flag = ParseFlag(xml::FindAttribute(parser, xml::kSchemaAndroid, "featureFlag")); std::unique_ptr<Item> value = ParseXml(parser, 0, kAllowRawString); if (!value) { diag_->Error(android::DiagMessage(source) << "could not parse style item"); return false; } if (flag) { if (options_.flag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Resource flag are not allowed both in the path and in the file"); return false; } std::string error; auto flag_status = GetFlagStatus(flag, options_.feature_flag_values, &error); if (flag_status) { value->SetFlagStatus(flag_status.value()); value->SetFlag(std::move(flag)); } else { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << error); return false; } } if (value->GetFlagStatus() != FlagStatus::Disabled) { style->entries.push_back(Style::Entry{std::move(maybe_key.value()), std::move(value)}); } return true; } Loading tools/aapt2/Resources.proto +5 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,11 @@ message CompoundValue { Plural plural = 5; MacroBody macro = 6; } // The status of the flag the value is behind if any uint32 flag_status = 7; bool flag_negated = 8; string flag_name = 9; } // Message holding a boolean, so it can be optionally encoded. Loading tools/aapt2/format/proto/ProtoDeserialize.cpp +9 −10 Original line number Diff line number Diff line Loading @@ -551,11 +551,10 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr return false; } FeatureFlagAttribute flag; flag.name = pb_config_value.value().item().flag_name(); flag.negated = pb_config_value.value().item().flag_negated(); ResourceConfigValue* config_value = entry->FindOrCreateFlagDisabledValue(std::move(flag), config, pb_config.product()); ResourceConfigValue* config_value = entry->FindOrCreateFlagDisabledValue( FeatureFlagAttribute{.name = pb_config_value.value().item().flag_name(), .negated = pb_config_value.value().item().flag_negated()}, config, pb_config.product()); if (config_value->value != nullptr) { *out_error = "duplicate configuration in resource table"; return false; Loading @@ -563,7 +562,6 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config, &out_table->string_pool, files, out_error); if (config_value->value == nullptr) { return false; } Loading Loading @@ -896,6 +894,9 @@ std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value, LOG(FATAL) << "unknown compound value: " << (int)pb_compound_value.value_case(); break; } value->SetFlagStatus((FlagStatus)pb_compound_value.flag_status()); value->SetFlag(FeatureFlagAttribute{.name = pb_compound_value.flag_name(), .negated = pb_compound_value.flag_negated()}); } else { LOG(FATAL) << "unknown value: " << (int)pb_value.value_case(); return {}; Loading Loading @@ -1052,10 +1053,8 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, if (item) { item->SetFlagStatus((FlagStatus)pb_item.flag_status()); if (!pb_item.flag_name().empty()) { FeatureFlagAttribute flag; flag.name = pb_item.flag_name(); flag.negated = pb_item.flag_negated(); item->SetFlag(std::move(flag)); item->SetFlag( FeatureFlagAttribute{.name = pb_item.flag_name(), .negated = pb_item.flag_negated()}); } } return item; Loading tools/aapt2/format/proto/ProtoSerialize.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -734,6 +734,13 @@ void SerializeValueToPb(const Value& value, pb::Value* out_value, android::Strin out_value->mutable_item()->set_flag_negated(flag->negated); out_value->mutable_item()->set_flag_name(flag->name); } } else if (out_value->has_compound_value()) { out_value->mutable_compound_value()->set_flag_status((uint32_t)value.GetFlagStatus()); if (value.GetFlag()) { const auto& flag = value.GetFlag(); out_value->mutable_compound_value()->set_flag_negated(flag->negated); out_value->mutable_compound_value()->set_flag_name(flag->name); } } } Loading Loading
core/tests/resourceflaggingtests/src/com/android/resourceflaggingtests/ResourceFlaggingTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.FileUtils; import android.util.DisplayMetrics; import android.view.LayoutInflater; Loading Loading @@ -151,6 +152,27 @@ public class ResourceFlaggingTest { mResources.getDrawable(R.drawable.removedpng); } @Test public void testDisabledStyleDoesntOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style1, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } @Test public void testEnabledStyleDoesOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style2, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } @Test public void testEnabledStyleItemDoesOverride() { TypedArray ta = mResources.newTheme().obtainStyledAttributes( R.style.style3, new int[] { android.R.attr.windowIsTranslucent}); assertThat(ta.getBoolean(0, false)).isTrue(); } private LayoutInflater getLayoutInflater() { ContextWrapper c = new ContextWrapper(mContext) { private LayoutInflater mInflater; Loading
tools/aapt2/ResourceParser.cpp +22 −1 Original line number Diff line number Diff line Loading @@ -1529,13 +1529,34 @@ bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) { ResolvePackage(parser, &maybe_key.value()); maybe_key.value().SetSource(source); auto flag = ParseFlag(xml::FindAttribute(parser, xml::kSchemaAndroid, "featureFlag")); std::unique_ptr<Item> value = ParseXml(parser, 0, kAllowRawString); if (!value) { diag_->Error(android::DiagMessage(source) << "could not parse style item"); return false; } if (flag) { if (options_.flag) { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << "Resource flag are not allowed both in the path and in the file"); return false; } std::string error; auto flag_status = GetFlagStatus(flag, options_.feature_flag_values, &error); if (flag_status) { value->SetFlagStatus(flag_status.value()); value->SetFlag(std::move(flag)); } else { diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number())) << error); return false; } } if (value->GetFlagStatus() != FlagStatus::Disabled) { style->entries.push_back(Style::Entry{std::move(maybe_key.value()), std::move(value)}); } return true; } Loading
tools/aapt2/Resources.proto +5 −0 Original line number Diff line number Diff line Loading @@ -302,6 +302,11 @@ message CompoundValue { Plural plural = 5; MacroBody macro = 6; } // The status of the flag the value is behind if any uint32 flag_status = 7; bool flag_negated = 8; string flag_name = 9; } // Message holding a boolean, so it can be optionally encoded. Loading
tools/aapt2/format/proto/ProtoDeserialize.cpp +9 −10 Original line number Diff line number Diff line Loading @@ -551,11 +551,10 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr return false; } FeatureFlagAttribute flag; flag.name = pb_config_value.value().item().flag_name(); flag.negated = pb_config_value.value().item().flag_negated(); ResourceConfigValue* config_value = entry->FindOrCreateFlagDisabledValue(std::move(flag), config, pb_config.product()); ResourceConfigValue* config_value = entry->FindOrCreateFlagDisabledValue( FeatureFlagAttribute{.name = pb_config_value.value().item().flag_name(), .negated = pb_config_value.value().item().flag_negated()}, config, pb_config.product()); if (config_value->value != nullptr) { *out_error = "duplicate configuration in resource table"; return false; Loading @@ -563,7 +562,6 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config, &out_table->string_pool, files, out_error); if (config_value->value == nullptr) { return false; } Loading Loading @@ -896,6 +894,9 @@ std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value, LOG(FATAL) << "unknown compound value: " << (int)pb_compound_value.value_case(); break; } value->SetFlagStatus((FlagStatus)pb_compound_value.flag_status()); value->SetFlag(FeatureFlagAttribute{.name = pb_compound_value.flag_name(), .negated = pb_compound_value.flag_negated()}); } else { LOG(FATAL) << "unknown value: " << (int)pb_value.value_case(); return {}; Loading Loading @@ -1052,10 +1053,8 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, if (item) { item->SetFlagStatus((FlagStatus)pb_item.flag_status()); if (!pb_item.flag_name().empty()) { FeatureFlagAttribute flag; flag.name = pb_item.flag_name(); flag.negated = pb_item.flag_negated(); item->SetFlag(std::move(flag)); item->SetFlag( FeatureFlagAttribute{.name = pb_item.flag_name(), .negated = pb_item.flag_negated()}); } } return item; Loading
tools/aapt2/format/proto/ProtoSerialize.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -734,6 +734,13 @@ void SerializeValueToPb(const Value& value, pb::Value* out_value, android::Strin out_value->mutable_item()->set_flag_negated(flag->negated); out_value->mutable_item()->set_flag_name(flag->name); } } else if (out_value->has_compound_value()) { out_value->mutable_compound_value()->set_flag_status((uint32_t)value.GetFlagStatus()); if (value.GetFlag()) { const auto& flag = value.GetFlag(); out_value->mutable_compound_value()->set_flag_negated(flag->negated); out_value->mutable_compound_value()->set_flag_name(flag->name); } } } Loading