Add ability to pass in a config string for FRROs

This enables passing them and and storing them in the .frro file but no
further.

Bug: 243066074
Test: Manual
Change-Id: I5c9723e69d175a536f9739619c6b6bf3162a5027
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 073d987..083bbf01 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -235,9 +235,11 @@
 
   for (const auto& res : overlay.entries) {
     if (res.dataType == Res_value::TYPE_STRING) {
-      builder.SetResourceValue(res.resourceName, res.dataType, res.stringData.value());
+      builder.SetResourceValue(res.resourceName, res.dataType, res.stringData.value(),
+            res.configuration.value_or(std::string()));
     } else {
-      builder.SetResourceValue(res.resourceName, res.dataType, res.data);
+      builder.SetResourceValue(res.resourceName, res.dataType, res.data,
+            res.configuration.value_or(std::string()));
     }
   }
 
diff --git a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl
index a6824da..c773e11 100644
--- a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl
+++ b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl
@@ -24,4 +24,5 @@
     int dataType;
     int data;
     @nullable @utf8InCpp String stringData;
+    @nullable @utf8InCpp String configuration;
 }
\ No newline at end of file
diff --git a/cmds/idmap2/include/idmap2/FabricatedOverlay.h b/cmds/idmap2/include/idmap2/FabricatedOverlay.h
index 2fc4d43..05b0618 100644
--- a/cmds/idmap2/include/idmap2/FabricatedOverlay.h
+++ b/cmds/idmap2/include/idmap2/FabricatedOverlay.h
@@ -39,10 +39,11 @@
     Builder& SetOverlayable(const std::string& name);
 
     Builder& SetResourceValue(const std::string& resource_name, uint8_t data_type,
-                              uint32_t data_value);
+                              uint32_t data_value, const std::string& configuration);
 
     Builder& SetResourceValue(const std::string& resource_name, uint8_t data_type,
-                              const std::string& data_string_value);
+                              const std::string& data_string_value,
+                              const std::string& configuration);
 
     WARN_UNUSED Result<FabricatedOverlay> Build();
 
@@ -52,6 +53,7 @@
       DataType data_type;
       DataValue data_value;
       std::string data_string_value;
+      std::string configuration;
     };
 
     std::string package_name_;
diff --git a/cmds/idmap2/include/idmap2/ResourceContainer.h b/cmds/idmap2/include/idmap2/ResourceContainer.h
index c3ba464..2452ff0 100644
--- a/cmds/idmap2/include/idmap2/ResourceContainer.h
+++ b/cmds/idmap2/include/idmap2/ResourceContainer.h
@@ -66,7 +66,7 @@
 
   struct Value {
     std::string resource_name;
-    std::variant<ResourceIdValue, TargetValue> value;
+    std::variant<ResourceIdValue, TargetValueWithConfig> value;
   };
 
   struct InlineStringPoolData {
diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h
index 5a0a384..21862a36 100644
--- a/cmds/idmap2/include/idmap2/ResourceMapping.h
+++ b/cmds/idmap2/include/idmap2/ResourceMapping.h
@@ -69,7 +69,8 @@
   // If `allow_rewriting_` is true, then the overlay-to-target map will be populated if the target
   // resource id is mapped to an overlay resource id.
   Result<Unit> AddMapping(ResourceId target_resource,
-                          const std::variant<OverlayData::ResourceIdValue, TargetValue>& value);
+                          const std::variant<OverlayData::ResourceIdValue,
+                          TargetValueWithConfig>& value);
 
   TargetResourceMap target_map_;
   OverlayResourceMap overlay_map_;
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 414aa06..8ec7496 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -43,6 +43,11 @@
   std::string data_string_value;
 };
 
+struct TargetValueWithConfig {
+  TargetValue value;
+  std::string config;
+};
+
 namespace utils {
 
 // Returns whether the Res_value::data_type represents a dynamic or regular resource reference.
diff --git a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp
index 5bbe085..bde9b0b 100644
--- a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp
+++ b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp
@@ -70,19 +70,22 @@
 }
 
 FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue(
-    const std::string& resource_name, uint8_t data_type, uint32_t data_value) {
-  entries_.emplace_back(Entry{resource_name, data_type, data_value, ""});
+    const std::string& resource_name, uint8_t data_type, uint32_t data_value,
+    const std::string& configuration) {
+  entries_.emplace_back(Entry{resource_name, data_type, data_value, "", configuration});
   return *this;
 }
 
 FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue(
-    const std::string& resource_name, uint8_t data_type, const std::string& data_string_value) {
-  entries_.emplace_back(Entry{resource_name, data_type, 0, data_string_value});
+    const std::string& resource_name, uint8_t data_type, const std::string& data_string_value,
+    const std::string& configuration) {
+  entries_.emplace_back(Entry{resource_name, data_type, 0, data_string_value, configuration});
   return *this;
 }
 
 Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() {
-  using EntryMap = std::map<std::string, TargetValue>;
+  using ConfigMap = std::map<std::string, TargetValue>;
+  using EntryMap = std::map<std::string, ConfigMap>;
   using TypeMap = std::map<std::string, EntryMap>;
   using PackageMap = std::map<std::string, TypeMap>;
   PackageMap package_map;
@@ -123,11 +126,16 @@
 
     auto entry = type->second.find(entry_name.to_string());
     if (entry == type->second.end()) {
-      entry = type->second.insert(std::make_pair(entry_name.to_string(), TargetValue())).first;
+      entry = type->second.insert(std::make_pair(entry_name.to_string(), ConfigMap())).first;
     }
 
-    entry->second = TargetValue{
-        res_entry.data_type, res_entry.data_value, res_entry.data_string_value};
+    auto value = entry->second.find(res_entry.configuration);
+    if (value == entry->second.end()) {
+      value = entry->second.insert(std::make_pair(res_entry.configuration, TargetValue())).first;
+    }
+
+    value->second = TargetValue{res_entry.data_type, res_entry.data_value,
+        res_entry.data_string_value};
   }
 
   pb::FabricatedOverlay overlay_pb;
@@ -145,15 +153,18 @@
       type_pb->set_name(type.first);
 
       for (auto& entry : type.second) {
-        auto entry_pb = type_pb->add_entries();
-        entry_pb->set_name(entry.first);
-        pb::ResourceValue* value = entry_pb->mutable_res_value();
-        value->set_data_type(entry.second.data_type);
-        if (entry.second.data_type == Res_value::TYPE_STRING) {
-          auto ref = string_pool.MakeRef(entry.second.data_string_value);
-          value->set_data_value(ref.index());
-        } else {
-          value->set_data_value(entry.second.data_value);
+        for (const auto& value: entry.second) {
+          auto entry_pb = type_pb->add_entries();
+          entry_pb->set_name(entry.first);
+          entry_pb->set_configuration(value.first);
+          pb::ResourceValue* pb_value = entry_pb->mutable_res_value();
+          pb_value->set_data_type(value.second.data_type);
+          if (value.second.data_type == Res_value::TYPE_STRING) {
+            auto ref = string_pool.MakeRef(value.second.data_string_value);
+            pb_value->set_data_value(ref.index());
+          } else {
+            pb_value->set_data_value(value.second.data_value);
+          }
         }
       }
     }
@@ -330,8 +341,9 @@
                                        entry.name().c_str());
         const auto& res_value = entry.res_value();
         result.pairs.emplace_back(OverlayData::Value{
-            name, TargetValue{.data_type = static_cast<uint8_t>(res_value.data_type()),
-                              .data_value = res_value.data_value()}});
+            name, TargetValueWithConfig{.config = entry.configuration(), .value = TargetValue{
+                    .data_type = static_cast<uint8_t>(res_value.data_type()),
+                    .data_value = res_value.data_value()}}});
       }
     }
   }
diff --git a/cmds/idmap2/libidmap2/ResourceContainer.cpp b/cmds/idmap2/libidmap2/ResourceContainer.cpp
index a62472c..0e35904 100644
--- a/cmds/idmap2/libidmap2/ResourceContainer.cpp
+++ b/cmds/idmap2/libidmap2/ResourceContainer.cpp
@@ -226,8 +226,10 @@
           *target_resource, OverlayData::ResourceIdValue{overlay_resource->data, rewrite_id}});
     } else {
       overlay_data.pairs.emplace_back(
-          OverlayData::Value{*target_resource, TargetValue{.data_type = overlay_resource->dataType,
-                                                           .data_value = overlay_resource->data}});
+          OverlayData::Value{*target_resource, TargetValueWithConfig{
+              .config = std::string(),
+              .value = TargetValue{.data_type = overlay_resource->dataType,
+                                   .data_value = overlay_resource->data}}});
     }
   }
 
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 3bbbf24..8ebe5aa4 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -160,7 +160,7 @@
 
 Result<Unit> ResourceMapping::AddMapping(
     ResourceId target_resource,
-    const std::variant<OverlayData::ResourceIdValue, TargetValue>& value) {
+    const std::variant<OverlayData::ResourceIdValue, TargetValueWithConfig>& value) {
   if (target_map_.find(target_resource) != target_map_.end()) {
     return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
   }
@@ -176,8 +176,8 @@
       overlay_map_.insert(std::make_pair(overlay_resource->overlay_id, target_resource));
     }
   } else {
-    auto overlay_value = std::get<TargetValue>(value);
-    target_map_.insert(std::make_pair(target_resource, overlay_value));
+    auto overlay_value = std::get<TargetValueWithConfig>(value);
+    target_map_.insert(std::make_pair(target_resource, overlay_value.value));
   }
 
   return Unit{};
diff --git a/cmds/idmap2/libidmap2/proto/fabricated_v1.proto b/cmds/idmap2/libidmap2/proto/fabricated_v1.proto
index a392b2b..c7a79b3 100644
--- a/cmds/idmap2/libidmap2/proto/fabricated_v1.proto
+++ b/cmds/idmap2/libidmap2/proto/fabricated_v1.proto
@@ -46,6 +46,7 @@
   oneof value {
     ResourceValue res_value = 2;
   }
+  string configuration = 3;
 }
 
 message ResourceValue {
diff --git a/cmds/idmap2/tests/FabricatedOverlayTests.cpp b/cmds/idmap2/tests/FabricatedOverlayTests.cpp
index 91331ca..e804c87 100644
--- a/cmds/idmap2/tests/FabricatedOverlayTests.cpp
+++ b/cmds/idmap2/tests/FabricatedOverlayTests.cpp
@@ -43,10 +43,17 @@
 TEST(FabricatedOverlayTests, SetResourceValue) {
   auto overlay =
       FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
-          .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U)
-          .SetResourceValue("com.example.target.split:integer/int2", Res_value::TYPE_INT_DEC, 2U)
-          .SetResourceValue("string/int3", Res_value::TYPE_REFERENCE, 0x7f010000)
-          .SetResourceValue("com.example.target:string/string1", Res_value::TYPE_STRING, "foobar")
+          .SetResourceValue(
+              "com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U, "port")
+          .SetResourceValue(
+              "com.example.target.split:integer/int2", Res_value::TYPE_INT_DEC, 2U, "land")
+          .SetResourceValue(
+              "string/int3", Res_value::TYPE_REFERENCE, 0x7f010000, "xxhdpi-v7")
+          .SetResourceValue(
+              "com.example.target:string/string1",
+              Res_value::TYPE_STRING,
+              "foobar",
+              "en-rUS-normal-xxhdpi-v21")
           .Build();
   ASSERT_TRUE(overlay);
   auto container = FabricatedOverlayContainer::FromOverlay(std::move(*overlay));
@@ -66,44 +73,48 @@
 
   auto& it = pairs->pairs[0];
   ASSERT_EQ("com.example.target:integer/int1", it.resource_name);
-  auto entry = std::get_if<TargetValue>(&it.value);
+  auto entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  ASSERT_EQ(1U, entry->data_value);
-  ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+  ASSERT_EQ(1U, entry->value.data_value);
+  ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type);
+  ASSERT_EQ("port", entry->config);
 
   it = pairs->pairs[1];
   ASSERT_EQ("com.example.target:string/int3", it.resource_name);
-  entry = std::get_if<TargetValue>(&it.value);
+  entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  ASSERT_EQ(0x7f010000, entry->data_value);
-  ASSERT_EQ(Res_value::TYPE_REFERENCE, entry->data_type);
+  ASSERT_EQ(0x7f010000, entry->value.data_value);
+  ASSERT_EQ(Res_value::TYPE_REFERENCE, entry->value.data_type);
+  ASSERT_EQ("xxhdpi-v7", entry->config);
 
   it = pairs->pairs[2];
   ASSERT_EQ("com.example.target:string/string1", it.resource_name);
-  entry = std::get_if<TargetValue>(&it.value);
+  entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  ASSERT_EQ(Res_value::TYPE_STRING, entry->data_type);
-  ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->data_value).value_or(""));
+  ASSERT_EQ(Res_value::TYPE_STRING, entry->value.data_type);
+  ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->value.data_value).value_or(""));
+  ASSERT_EQ("en-rUS-normal-xxhdpi-v21", entry->config);
 
   it = pairs->pairs[3];
   ASSERT_EQ("com.example.target.split:integer/int2", it.resource_name);
-  entry = std::get_if<TargetValue>(&it.value);
+  entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  ASSERT_EQ(2U, entry->data_value);
-  ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+  ASSERT_EQ(2U, entry->value.data_value);
+  ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type);
+  ASSERT_EQ("land", entry->config);
 }
 
 TEST(FabricatedOverlayTests, SetResourceValueBadArgs) {
   {
     auto builder =
         FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
-            .SetResourceValue("int1", Res_value::TYPE_INT_DEC, 1U);
+            .SetResourceValue("int1", Res_value::TYPE_INT_DEC, 1U, "");
     ASSERT_FALSE(builder.Build());
   }
   {
     auto builder =
         FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
-            .SetResourceValue("com.example.target:int2", Res_value::TYPE_INT_DEC, 1U);
+            .SetResourceValue("com.example.target:int2", Res_value::TYPE_INT_DEC, 1U, "");
     ASSERT_FALSE(builder.Build());
   }
 }
@@ -112,8 +123,9 @@
   auto overlay =
       FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
           .SetOverlayable("TestResources")
-          .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U)
-          .SetResourceValue("com.example.target:string/string1", Res_value::TYPE_STRING, "foobar")
+          .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U, "")
+          .SetResourceValue(
+              "com.example.target:string/string1", Res_value::TYPE_STRING, "foobar", "")
           .Build();
   ASSERT_TRUE(overlay);
   TemporaryFile tf;
@@ -142,17 +154,17 @@
 
   auto& it = pairs->pairs[0];
   ASSERT_EQ("com.example.target:integer/int1", it.resource_name);
-  auto entry = std::get_if<TargetValue>(&it.value);
+  auto entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  EXPECT_EQ(1U, entry->data_value);
-  EXPECT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+  EXPECT_EQ(1U, entry->value.data_value);
+  EXPECT_EQ(Res_value::TYPE_INT_DEC, entry->value.data_type);
 
   it = pairs->pairs[1];
   ASSERT_EQ("com.example.target:string/string1", it.resource_name);
-  entry = std::get_if<TargetValue>(&it.value);
+  entry = std::get_if<TargetValueWithConfig>(&it.value);
   ASSERT_NE(nullptr, entry);
-  ASSERT_EQ(Res_value::TYPE_STRING, entry->data_type);
-  ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->data_value).value_or(""));
+  ASSERT_EQ(Res_value::TYPE_STRING, entry->value.data_type);
+  ASSERT_EQ(std::string("foobar"), string_pool.string8At(entry->value.data_value).value_or(""));
 }
 
 }  // namespace android::idmap2
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index a3799f9..ee9a424 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -261,9 +261,9 @@
 
   auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target")
                   .SetOverlayable("TestResources")
-                  .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U)
-                  .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000)
-                  .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar")
+                  .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "")
+                  .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "")
+                  .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "")
                   .Build();
 
   ASSERT_TRUE(frro);
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index c05abcf..ca9a444 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -194,9 +194,9 @@
 TEST(ResourceMappingTests, FabricatedOverlay) {
   auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target")
                   .SetOverlayable("TestResources")
-                  .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U)
-                  .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000)
-                  .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar")
+                  .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "")
+                  .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "")
+                  .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "")
                   .Build();
 
   ASSERT_TRUE(frro);
diff --git a/core/java/android/content/om/FabricatedOverlay.java b/core/java/android/content/om/FabricatedOverlay.java
index 5efc1f9..3ca0560 100644
--- a/core/java/android/content/om/FabricatedOverlay.java
+++ b/core/java/android/content/om/FabricatedOverlay.java
@@ -112,6 +112,28 @@
          * @param resourceName name of the target resource to overlay (in the form
          *                     [package]:type/entry)
          * @param dataType the data type of the new value
+         * @param value the unsigned 32 bit integer representing the new value
+         * @param configuration The string representation of the config this overlay is enabled for
+         *
+         * @see android.util.TypedValue#type
+         */
+        public Builder setResourceValue(@NonNull String resourceName, int dataType, int value,
+                String configuration) {
+            final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
+            entry.resourceName = resourceName;
+            entry.dataType = dataType;
+            entry.data = value;
+            entry.configuration = configuration;
+            mEntries.add(entry);
+            return this;
+        }
+
+        /**
+         * Sets the value of the fabricated overlay
+         *
+         * @param resourceName name of the target resource to overlay (in the form
+         *                     [package]:type/entry)
+         * @param dataType the data type of the new value
          * @param value the string representing the new value
          *
          * @see android.util.TypedValue#type
@@ -125,6 +147,28 @@
             return this;
         }
 
+        /**
+         * Sets the value of the fabricated overlay
+         *
+         * @param resourceName name of the target resource to overlay (in the form
+         *                     [package]:type/entry)
+         * @param dataType the data type of the new value
+         * @param value the string representing the new value
+         * @param configuration The string representation of the config this overlay is enabled for
+         *
+         * @see android.util.TypedValue#type
+         */
+        public Builder setResourceValue(@NonNull String resourceName, int dataType, String value,
+                String configuration) {
+            final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
+            entry.resourceName = resourceName;
+            entry.dataType = dataType;
+            entry.stringData = value;
+            entry.configuration = configuration;
+            mEntries.add(entry);
+            return this;
+        }
+
         /** Builds an immutable fabricated overlay. */
         public FabricatedOverlay build() {
             final FabricatedOverlayInternal overlay = new FabricatedOverlayInternal();
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index da76738..bb918d5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -257,6 +257,7 @@
         String name = "";
         String filename = null;
         String opt;
+        String configuration = null;
         while ((opt = getNextOption()) != null) {
             switch (opt) {
                 case "--user":
@@ -274,6 +275,9 @@
                 case "--file":
                     filename = getNextArgRequired();
                     break;
+                case "--config":
+                    configuration = getNextArgRequired();
+                    break;
                 default:
                     err.println("Error: Unknown option: " + opt);
                     return 1;
@@ -307,7 +311,7 @@
             final String resourceName = getNextArgRequired();
             final String typeStr = getNextArgRequired();
             final String strData = String.join(" ", peekRemainingArgs());
-            addOverlayValue(overlayBuilder, resourceName, typeStr, strData);
+            addOverlayValue(overlayBuilder, resourceName, typeStr, strData, configuration);
         }
 
         mInterface.commit(new OverlayManagerTransaction.Builder()
@@ -363,8 +367,9 @@
                             err.println("Error: value missing at line " + parser.getLineNumber());
                             return 1;
                         }
+                        String config = parser.getAttributeValue(null, "config");
                         addOverlayValue(overlayBuilder, targetPackage + ':' + target,
-                                overlayType, value);
+                                overlayType, value, config);
                     }
                 }
             }
@@ -379,7 +384,7 @@
     }
 
     private void addOverlayValue(FabricatedOverlay.Builder overlayBuilder,
-            String resourceName, String typeString, String valueString) {
+            String resourceName, String typeString, String valueString, String configuration) {
         final int type;
         typeString = typeString.toLowerCase(Locale.getDefault());
         if (TYPE_MAP.containsKey(typeString)) {
@@ -392,7 +397,7 @@
             }
         }
         if (type == TypedValue.TYPE_STRING) {
-            overlayBuilder.setResourceValue(resourceName, type, valueString);
+            overlayBuilder.setResourceValue(resourceName, type, valueString, configuration);
         } else {
             final int intData;
             if (valueString.startsWith("0x")) {
@@ -400,7 +405,7 @@
             } else {
                 intData = Integer.parseUnsignedInt(valueString);
             }
-            overlayBuilder.setResourceValue(resourceName, type, intData);
+            overlayBuilder.setResourceValue(resourceName, type, intData, configuration);
         }
     }