Pseudolocale support for grammatical gender

Default behavior is generate grammatical gender strings with different
prefix when pseudolocale is enabled. Also extend two specifiers to
support generate grammatical gender string for a specific gender and for
a spefific ratio. go/pseudolocale-support-for-grammatical-gender

Bug: b/272626712
Test: Added and verified affected atests pass
Change-Id: I6b7514425898facb68f0b1f6fb09e4f87978c03d
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index d2ea599..b5c290e 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -186,7 +186,20 @@
     // These are created as weak symbols, and are only generated from default
     // configuration
     // strings and plurals.
-    PseudolocaleGenerator pseudolocale_generator;
+    std::string grammatical_gender_values;
+    std::string grammatical_gender_ratio;
+    if (options.pseudo_localize_gender_values) {
+      grammatical_gender_values = options.pseudo_localize_gender_values.value();
+    } else {
+      grammatical_gender_values = "f,m,n";
+    }
+    if (options.pseudo_localize_gender_ratio) {
+      grammatical_gender_ratio = options.pseudo_localize_gender_ratio.value();
+    } else {
+      grammatical_gender_ratio = "1.0";
+    }
+    PseudolocaleGenerator pseudolocale_generator(grammatical_gender_values,
+                                                 grammatical_gender_ratio);
     if (!pseudolocale_generator.Consume(context, &table)) {
       return false;
     }
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index 14a730a..22890fc 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -35,6 +35,8 @@
   std::optional<std::string> res_dir;
   std::optional<std::string> res_zip;
   std::optional<std::string> generate_text_symbols_path;
+  std::optional<std::string> pseudo_localize_gender_values;
+  std::optional<std::string> pseudo_localize_gender_ratio;
   std::optional<Visibility::Level> visibility;
   bool pseudolocalize = false;
   bool no_png_crunch = false;
@@ -76,6 +78,15 @@
     AddOptionalFlag("--source-path",
                       "Sets the compiled resource file source file path to the given string.",
                       &options_.source_path);
+    AddOptionalFlag("--pseudo-localize-gender-values",
+                    "Sets the gender values to pick up for generating grammatical gender strings, "
+                    "gender values should be f, m, or n, which are shortcuts for feminine, "
+                    "masculine and neuter, and split with comma.",
+                    &options_.pseudo_localize_gender_values);
+    AddOptionalFlag("--pseudo-localize-gender-ratio",
+                    "Sets the ratio of resources to generate grammatical gender strings for. The "
+                    "ratio has to be a float number between 0 and 1.",
+                    &options_.pseudo_localize_gender_ratio);
   }
 
   int Action(const std::vector<std::string>& args) override;
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 3464a76..8880089 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -236,9 +236,24 @@
   // The first string (000) is translatable, the second is not
   // ar-XB uses "\u200F\u202E...\u202C\u200F"
   std::vector<std::string> expected_translatable = {
-      "000", "111", // default locale
-      "[000 one]", // en-XA
-      "\xE2\x80\x8F\xE2\x80\xAE" "000" "\xE2\x80\xAC\xE2\x80\x8F", // ar-XB
+      "(F)[000 one]",  // en-XA-feminine
+      "(F)\xE2\x80\x8F\xE2\x80\xAE"
+      "000"
+      "\xE2\x80\xAC\xE2\x80\x8F",  // ar-XB-feminine
+      "(M)[000 one]",              // en-XA-masculine
+      "(M)\xE2\x80\x8F\xE2\x80\xAE"
+      "000"
+      "\xE2\x80\xAC\xE2\x80\x8F",  // ar-XB-masculine
+      "(N)[000 one]",              // en-XA-neuter
+      "(N)\xE2\x80\x8F\xE2\x80\xAE"
+      "000"
+      "\xE2\x80\xAC\xE2\x80\x8F",  // ar-XB-neuter
+      "000",                       // default locale
+      "111",                       // default locale
+      "[000 one]",                 // en-XA
+      "\xE2\x80\x8F\xE2\x80\xAE"
+      "000"
+      "\xE2\x80\xAC\xE2\x80\x8F",  // ar-XB
   };
   AssertTranslations(this, "foo", expected_translatable);
   AssertTranslations(this, "foo_donottranslate", expected_translatable);