Add flag support to styles elements

Test: Automated
Bug: 329436914
Flag: EXEMPT Aconfig not supported on host tools
Change-Id: I3041ebbaf98a90527809b541df8885edfc70d035
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index fce6aa7..da092f4 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1529,13 +1529,34 @@
   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;
   }
 
-  style->entries.push_back(Style::Entry{std::move(maybe_key.value()), std::move(value)});
+  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;
 }
 
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index a0f60b6..fe9b4a8 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -302,6 +302,11 @@
     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.
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 8583cad..91ec348 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -551,11 +551,10 @@
           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;
@@ -563,7 +562,6 @@
 
         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;
         }
@@ -896,6 +894,9 @@
         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 {};
@@ -1052,10 +1053,8 @@
   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;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index d83fe91..fcc77d5 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -734,6 +734,13 @@
       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);
+    }
   }
 }
 
diff --git a/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp b/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp
index 7160b35..1b0f997 100644
--- a/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp
+++ b/tools/aapt2/integration-tests/FlaggedResourcesTest/Android.bp
@@ -30,6 +30,7 @@
         "res/values/bools2.xml",
         "res/values/ints.xml",
         "res/values/strings.xml",
+        "res/values/styles.xml",
         "res/layout/layout1.xml",
         "res/layout/layout3.xml",
         "res/flag(test.package.falseFlag)/values/bools.xml",
@@ -50,6 +51,7 @@
         "values_bools2.arsc.flat",
         "values_ints.arsc.flat",
         "values_strings.arsc.flat",
+        "values_styles.arsc.flat",
         "layout_layout1.xml.flat",
         "layout_layout2.(test.package.falseFlag).xml.flat",
         "layout_layout3.xml.flat",
diff --git a/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/styles.xml b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/styles.xml
new file mode 100644
index 0000000..604129c
--- /dev/null
+++ b/tools/aapt2/integration-tests/FlaggedResourcesTest/res/values/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <style name="style1">
+        <item name="android:windowIsTranslucent">true</item>
+    </style>
+    <style name="style1" android:featureFlag="test.package.falseFlag">
+        <item name="android:windowIsTranslucent">false</item>
+    </style>
+
+    <style name="style2">
+        <item name="android:windowIsTranslucent">false</item>
+    </style>
+    <style name="style2" android:featureFlag="test.package.trueFlag">
+        <item name="android:windowIsTranslucent">true</item>
+    </style>
+
+    <style name="style3">
+        <item name="android:windowIsTranslucent" android:featureFlag="!test.package.trueFlag">false</item>
+        <item name="android:windowIsTranslucent" android:featureFlag="test.package.trueFlag">true</item>
+    </style>
+</resources>
\ No newline at end of file