Store frro configs in idmap file

This also includes the change to use the configs to decide which (if
any) frros to use at runtime

Bug: 243066074
Test: Manual, updated and created automated tests
Change-Id: I3f1d23e2958ad170799880b9f5eb5bd8ceb1fa67
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 06650f6..4efaeea 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -186,6 +186,8 @@
   std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
   if (!Read32(stream, &idmap_data_header->target_entry_count) ||
       !Read32(stream, &idmap_data_header->target_entry_inline_count) ||
+      !Read32(stream, &idmap_data_header->target_entry_inline_value_count) ||
+      !Read32(stream, &idmap_data_header->config_count) ||
       !Read32(stream, &idmap_data_header->overlay_entry_count) ||
       !Read32(stream, &idmap_data_header->string_pool_index_offset)) {
     return nullptr;
@@ -207,20 +209,59 @@
     if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) {
       return nullptr;
     }
-    data->target_entries_.push_back(target_entry);
+    data->target_entries_.emplace_back(target_entry);
   }
 
   // Read the mapping of target resource id to inline overlay values.
-  uint8_t unused1;
-  uint16_t unused2;
+  std::vector<std::tuple<TargetInlineEntry, uint32_t, uint32_t>> target_inline_entries;
   for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) {
     TargetInlineEntry target_entry{};
-    if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) ||
-        !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) ||
-        !Read32(stream, &target_entry.value.data_value)) {
+    uint32_t entry_offset;
+    uint32_t entry_count;
+    if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &entry_offset)
+        || !Read32(stream, &entry_count)) {
       return nullptr;
     }
-    data->target_inline_entries_.push_back(target_entry);
+    target_inline_entries.emplace_back(std::make_tuple(target_entry, entry_offset, entry_count));
+  }
+
+  // Read the inline overlay resource values
+  std::vector<std::pair<uint32_t, TargetValue>> target_values;
+  uint8_t unused1;
+  uint16_t unused2;
+  for (size_t i = 0; i < data->header_->GetTargetInlineEntryValueCount(); i++) {
+    uint32_t config_index;
+    if (!Read32(stream, &config_index)) {
+      return nullptr;
+    }
+    TargetValue value;
+    if (!Read16(stream, &unused2)
+        || !Read8(stream, &unused1)
+        || !Read8(stream, &value.data_type)
+        || !Read32(stream, &value.data_value)) {
+      return nullptr;
+    }
+    target_values.emplace_back(std::make_pair(config_index, value));
+  }
+
+  // Read the configurations
+  std::vector<ConfigDescription> configurations;
+  for (size_t i = 0; i < data->header_->GetConfigCount(); i++) {
+    ConfigDescription cd;
+    if (!stream.read(reinterpret_cast<char*>(&cd), sizeof(ConfigDescription))) {
+      return nullptr;
+    }
+    configurations.emplace_back(cd);
+  }
+
+  // Construct complete target inline entries
+  for (auto [target_entry, entry_offset, entry_count] : target_inline_entries) {
+    for(size_t i = 0; i < entry_count; i++) {
+      const auto& target_value = target_values[entry_offset + i];
+      const auto& config = configurations[target_value.first];
+      target_entry.values[config] = target_value.second;
+    }
+    data->target_inline_entries_.emplace_back(target_entry);
   }
 
   // Read the mapping of overlay resource id to target resource id.
@@ -278,12 +319,21 @@
 
   std::unique_ptr<IdmapData> data(new IdmapData());
   data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string();
+  uint32_t inline_value_count = 0;
+  std::set<std::string> config_set;
   for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) {
     if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) {
       data->target_entries_.push_back({mapping.first, *overlay_resource});
     } else {
-      data->target_inline_entries_.push_back(
-          {mapping.first, std::get<TargetValue>(mapping.second)});
+      std::map<ConfigDescription, TargetValue> values;
+      for (const auto& [config, value] : std::get<ConfigMap>(mapping.second)) {
+        config_set.insert(config);
+        ConfigDescription cd;
+        ConfigDescription::Parse(config, &cd);
+        values[cd] = value;
+        inline_value_count++;
+      }
+      data->target_inline_entries_.push_back({mapping.first, values});
     }
   }
 
@@ -295,6 +345,8 @@
   data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
   data_header->target_entry_inline_count =
       static_cast<uint32_t>(data->target_inline_entries_.size());
+  data_header->target_entry_inline_value_count = inline_value_count;
+  data_header->config_count = config_set.size();
   data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
   data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
   data->header_ = std::move(data_header);