Clear variation settings when setTypeface is called

Bug: 353609778
Test: atest CtsGraphicsTestCases:android.graphics.cts.PaintTest
Flag: com.android.text.flags.clear_font_variation_settings
Change-Id: I0fa4ef077cc36cff2c5e34165cfe1c63d5e66854
diff --git a/core/java/android/text/ClientFlags.java b/core/java/android/text/ClientFlags.java
index 5d84d17..b07534f 100644
--- a/core/java/android/text/ClientFlags.java
+++ b/core/java/android/text/ClientFlags.java
@@ -68,4 +68,11 @@
     public static boolean fixMisalignedContextMenu() {
         return TextFlags.isFeatureEnabled(Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU);
     }
+
+    /**
+     * @see Flags#clearFontVariationSettings()
+     */
+    public static boolean clearFontVariationSettings() {
+        return TextFlags.isFeatureEnabled(Flags.FLAG_CLEAR_FONT_VARIATION_SETTINGS);
+    }
 }
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
index 9e02460..4dca284 100644
--- a/core/java/android/text/TextFlags.java
+++ b/core/java/android/text/TextFlags.java
@@ -61,6 +61,7 @@
             Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE,
             Flags.FLAG_ICU_BIDI_MIGRATION,
             Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU,
+            Flags.FLAG_CLEAR_FONT_VARIATION_SETTINGS,
     };
 
     /**
@@ -75,6 +76,7 @@
             Flags.fixLineHeightForLocale(),
             Flags.icuBidiMigration(),
             Flags.fixMisalignedContextMenu(),
+            Flags.clearFontVariationSettings(),
     };
 
     /**
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 8836c8a..6b1ea26 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -220,3 +220,14 @@
   is_fixed_read_only: true
   bug: "346915432"
 }
+
+flag {
+  name: "clear_font_variation_settings"
+  namespace: "text"
+  description: "The font variation settings must be cleared when the new Typeface is set"
+  bug: "353609778"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index df95a91..b83931f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -35,6 +35,7 @@
 import android.graphics.fonts.FontVariationAxis;
 import android.os.Build;
 import android.os.LocaleList;
+import android.text.ClientFlags;
 import android.text.GraphicsOperations;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -1540,8 +1541,21 @@
      * @return         typeface
      */
     public Typeface setTypeface(Typeface typeface) {
+        return setTypefaceInternal(typeface, true);
+    }
+
+    private Typeface setTypefaceInternal(Typeface typeface, boolean clearFontVariationSettings) {
         final long typefaceNative = typeface == null ? 0 : typeface.native_instance;
         nSetTypeface(mNativePaint, typefaceNative);
+
+        if (ClientFlags.clearFontVariationSettings()) {
+            if (clearFontVariationSettings && !Objects.equals(mTypeface, typeface)) {
+                // We cannot call setFontVariationSetting with empty string or null because it calls
+                // setTypeface method. To avoid recursive setTypeface call, manually resetting
+                // mFontVariationSettings.
+                mFontVariationSettings = null;
+            }
+        }
         mTypeface = typeface;
         return typeface;
     }
@@ -2037,6 +2051,14 @@
      * </li>
      * </ul>
      *
+     * Note: This method replaces the Typeface previously set to this instance.
+     * Until API {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, any caller of
+     * {@link #setTypeface(Typeface)} should call this method with empty settings, then call
+     * {@link #setTypeface(Typeface)}, then call this method with preferred variation settings.
+     * The device API more than {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, the
+     * {@link #setTypeface(Typeface)} method clears font variation settings. So caller of
+     * {@link #setTypeface(Typeface)} should call this method again for applying variation settings.
+     *
      * @param fontVariationSettings font variation settings. You can pass null or empty string as
      *                              no variation settings.
      *
@@ -2059,8 +2081,8 @@
 
         if (settings == null || settings.length() == 0) {
             mFontVariationSettings = null;
-            setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface,
-                      Collections.emptyList()));
+            setTypefaceInternal(Typeface.createFromTypefaceWithVariation(mTypeface,
+                      Collections.emptyList()), false);
             return true;
         }
 
@@ -2078,7 +2100,8 @@
             return false;
         }
         mFontVariationSettings = settings;
-        setTypeface(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes));
+        setTypefaceInternal(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes),
+                false);
         return true;
     }