AAPT2: Set the minSdkVersion when generating multiple APKs.

When generating multiple APKs from a configuration file, check to see if
we have filtered resource by minSdkVersion and update the manifest to
reflect this. We only want to inflate and modify the manifest file if
there is an update to be applied.

Bug: 37944703
Bug: 67005138

Test: Ran unit tests
Test: Manually split an APK and verified the manifest by dumping with
      AAPT (both xmltree and badging).

Change-Id: I64a0e4889d7d9e57373369b044a091287b06cc35
diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp
index 9d6d328..d2b4d72 100644
--- a/tools/aapt2/configuration/ConfigurationParser.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser.cpp
@@ -27,6 +27,7 @@
 
 #include "ConfigDescription.h"
 #include "Diagnostics.h"
+#include "ResourceUtils.h"
 #include "io/File.h"
 #include "io/FileSystem.h"
 #include "io/StringInputStream.h"
@@ -499,11 +500,11 @@
       AndroidSdk entry;
       for (const auto& attr : child->attributes) {
         if (attr.name == "minSdkVersion") {
-          entry.min_sdk_version = {attr.value};
+          entry.min_sdk_version = ResourceUtils::ParseSdkVersion(attr.value);
         } else if (attr.name == "targetSdkVersion") {
-          entry.target_sdk_version = {attr.value};
+          entry.target_sdk_version = ResourceUtils::ParseSdkVersion(attr.value);
         } else if (attr.name == "maxSdkVersion") {
-          entry.max_sdk_version = {attr.value};
+          entry.max_sdk_version = ResourceUtils::ParseSdkVersion(attr.value);
         } else {
           diag->Warn(DiagMessage() << "Unknown attribute: " << attr.name << " = " << attr.value);
         }
diff --git a/tools/aapt2/configuration/ConfigurationParser.h b/tools/aapt2/configuration/ConfigurationParser.h
index 9bc9081..ebf1c98 100644
--- a/tools/aapt2/configuration/ConfigurationParser.h
+++ b/tools/aapt2/configuration/ConfigurationParser.h
@@ -103,14 +103,14 @@
 };
 
 struct AndroidSdk {
-  Maybe<std::string> min_sdk_version;
-  Maybe<std::string> target_sdk_version;
-  Maybe<std::string> max_sdk_version;
+  Maybe<int> min_sdk_version;
+  Maybe<int> target_sdk_version;
+  Maybe<int> max_sdk_version;
   Maybe<AndroidManifest> manifest;
 
-  static AndroidSdk ForMinSdk(std::string min_sdk) {
+  static AndroidSdk ForMinSdk(int min_sdk) {
     AndroidSdk sdk;
-    sdk.min_sdk_version = {std::move(min_sdk)};
+    sdk.min_sdk_version = min_sdk;
     return sdk;
   }
 
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index 7ffb3d5..6bb168f 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -24,6 +24,15 @@
 #include "xml/XmlDom.h"
 
 namespace aapt {
+
+namespace configuration {
+void PrintTo(const AndroidSdk& sdk, std::ostream* os) {
+  *os << "SDK: min=" << sdk.min_sdk_version.value_or_default(-1)
+      << ", target=" << sdk.target_sdk_version.value_or_default(-1)
+      << ", max=" << sdk.max_sdk_version.value_or_default(-1);
+}
+}  // namespace configuration
+
 namespace {
 
 using ::android::ResTable_config;
@@ -76,9 +85,9 @@
     </locale-group>
     <android-sdk-group label="v19">
       <android-sdk
-          minSdkVersion="v19"
-          targetSdkVersion="v24"
-          maxSdkVersion="v25">
+          minSdkVersion="19"
+          targetSdkVersion="24"
+          maxSdkVersion="25">
         <manifest>
           <!--- manifest additions here XSLT? TODO -->
         </manifest>
@@ -156,7 +165,7 @@
 
   EXPECT_EQ(1ul, value.android_sdk_groups.size());
   EXPECT_TRUE(value.android_sdk_groups["v19"].min_sdk_version);
-  EXPECT_EQ("v19", value.android_sdk_groups["v19"].min_sdk_version.value());
+  EXPECT_EQ(19, value.android_sdk_groups["v19"].min_sdk_version.value());
 
   EXPECT_EQ(1ul, value.gl_texture_groups.size());
   EXPECT_EQ(1ul, value.gl_texture_groups["dxt1"].size());
@@ -321,9 +330,9 @@
   static constexpr const char* xml = R"xml(
     <android-sdk-group label="v19">
       <android-sdk
-          minSdkVersion="v19"
-          targetSdkVersion="v24"
-          maxSdkVersion="v25">
+          minSdkVersion="19"
+          targetSdkVersion="24"
+          maxSdkVersion="25">
         <manifest>
           <!--- manifest additions here XSLT? TODO -->
         </manifest>
@@ -342,14 +351,43 @@
   auto& out = config.android_sdk_groups["v19"];
 
   AndroidSdk sdk;
-  sdk.min_sdk_version = std::string("v19");
-  sdk.target_sdk_version = std::string("v24");
-  sdk.max_sdk_version = std::string("v25");
+  sdk.min_sdk_version = 19;
+  sdk.target_sdk_version = 24;
+  sdk.max_sdk_version = 25;
   sdk.manifest = AndroidManifest();
 
   ASSERT_EQ(sdk, out);
 }
 
+TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) {
+  static constexpr const char* xml = R"xml(
+    <android-sdk-group label="O">
+      <android-sdk
+          minSdkVersion="M"
+          targetSdkVersion="O"
+          maxSdkVersion="O">
+      </android-sdk>
+    </android-sdk-group>)xml";
+
+  auto doc = test::BuildXmlDom(xml);
+
+  PostProcessingConfiguration config;
+  bool ok = android_sdk_group_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
+  ASSERT_TRUE(ok);
+
+  ASSERT_EQ(1ul, config.android_sdk_groups.size());
+  ASSERT_EQ(1u, config.android_sdk_groups.count("O"));
+
+  auto& out = config.android_sdk_groups["O"];
+
+  AndroidSdk sdk;
+  sdk.min_sdk_version = {};  // Only the latest development version is supported.
+  sdk.target_sdk_version = 26;
+  sdk.max_sdk_version = 26;
+
+  ASSERT_EQ(sdk, out);
+}
+
 TEST_F(ConfigurationParserTest, GlTextureGroupAction) {
   static constexpr const char* xml = R"xml(
     <gl-texture-group label="dxt1">