AAPT2: Auto-version adaptive-icon XML

Auto version adaptive-icon XML to v26.

This change makes the logic for generating versioned resources
simpler by changing the comparison function of ResTable_config
to evaluate the sdkVersion property last, making configurations
that differ only in sdkVersion next to each other in a sorted vector.

Bug: 62316340
Test: manual (verified output of tools/aapt2/integration-tests/AppOne)
Change-Id: I977d45821722a65d2135efb4693304eacc565c9a
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index f80c6e9..4ac70d9 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -34,6 +34,19 @@
   return sdk_version_to_generate < FindNextApiVersionForConfig(entry, config);
 }
 
+ApiVersion FindNextApiVersionForConfigInSortedVector(
+    std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator start,
+    std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator end) {
+  const ConfigDescription start_config = (*start)->config.CopyWithoutSdkVersion();
+  ++start;
+  if (start != end) {
+    if ((*start)->config.CopyWithoutSdkVersion() == start_config) {
+      return static_cast<ApiVersion>((*start)->config.sdkVersion);
+    }
+  }
+  return std::numeric_limits<ApiVersion>::max();
+}
+
 ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
                                        const ConfigDescription& config) {
   const auto end_iter = entry->values.end();
@@ -46,25 +59,7 @@
 
   // The source config came from this list, so it should be here.
   CHECK(iter != entry->values.end());
-  ++iter;
-
-  // The next configuration either only varies in sdkVersion, or it is completely different
-  // and therefore incompatible. If it is incompatible, we must generate the versioned resource.
-
-  // NOTE: The ordering of configurations takes sdkVersion as higher precedence than other
-  // qualifiers, so we need to iterate through the entire list to be sure there
-  // are no higher sdk level versions of this resource.
-  ConfigDescription temp_config(config);
-  for (; iter != end_iter; ++iter) {
-    temp_config.sdkVersion = (*iter)->config.sdkVersion;
-    if (temp_config == (*iter)->config) {
-      // The two configs are the same, return the sdkVersion.
-      return (*iter)->config.sdkVersion;
-    }
-  }
-
-  // Didn't find another config with a different sdk version, so return the highest possible value.
-  return std::numeric_limits<ApiVersion>::max();
+  return FindNextApiVersionForConfigInSortedVector(iter, end_iter);
 }
 
 bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 49639f8..88a831b 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -42,8 +42,8 @@
 
   ResourceEntry entry("foo");
   entry.values.push_back(util::make_unique<ResourceConfigValue>(ConfigDescription::DefaultConfig(), ""));
-  entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dp_v13_config, ""));
   entry.values.push_back(util::make_unique<ResourceConfigValue>(v21_config, ""));
+  entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dp_v13_config, ""));
 
   EXPECT_TRUE(ShouldGenerateVersionedResource(&entry, ConfigDescription::DefaultConfig(), 17));
   EXPECT_FALSE(ShouldGenerateVersionedResource(&entry, ConfigDescription::DefaultConfig(), 22));
diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h
index 5527f90..493b6b1 100644
--- a/tools/aapt2/link/Linkers.h
+++ b/tools/aapt2/link/Linkers.h
@@ -23,6 +23,7 @@
 #include "android-base/macros.h"
 
 #include "Resource.h"
+#include "ResourceTable.h"
 #include "SdkConstants.h"
 #include "process/IResourceTableConsumer.h"
 #include "xml/XmlDom.h"
@@ -41,17 +42,19 @@
   ResourceNameRef resource;
 };
 
-/**
- * Determines whether a versioned resource should be created. If a versioned
- * resource already exists, it takes precedence.
- */
+// Determines whether a versioned resource should be created. If a versioned resource already
+// exists, it takes precedence.
 bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
                                      const ApiVersion sdk_version_to_generate);
 
-// Finds the next largest ApiVersion of the config which is identical to the given config except
-// for sdkVersion.
+// Finds the next largest ApiVersion of `config` for values defined for `entry`.
 ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, const ConfigDescription& config);
 
+// Finds the next largest ApiVersion of the config pointed to by the iterator `start`.
+ApiVersion FindNextApiVersionForConfigInSortedVector(
+    std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator start,
+    std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator end);
+
 class AutoVersioner : public IResourceTableConsumer {
  public:
   AutoVersioner() = default;