Merge "Notify caller if none of settings are effective."
diff --git a/api/current.txt b/api/current.txt
index aab29be..6880c0b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13230,7 +13230,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -51263,7 +51263,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 5e6717c..3dac882 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13965,7 +13965,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -55092,7 +55092,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index f91bbb9..a891fde 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13268,7 +13268,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -51641,7 +51641,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 52e8ec8..f2a7f25 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3808,23 +3808,28 @@
      * @param fontVariationSettings font variation settings. You can pass null or empty string as
      *                              no variation settings.
      *
+     * @return true if the given settings is effective to at least one font file underlying this
+     *         TextView. This function also returns true for empty settings string. Otherwise
+     *         returns false.
+     *
      * @see #getFontVariationSettings()
      * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
      */
-    public void setFontVariationSettings(@Nullable String fontVariationSettings) {
+    public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
         final String existingSettings = mTextPaint.getFontVariationSettings();
         if (fontVariationSettings == existingSettings
                 || (fontVariationSettings != null
                         && fontVariationSettings.equals(existingSettings))) {
-            return;
+            return true;
         }
-        mTextPaint.setFontVariationSettings(fontVariationSettings);
+        boolean effective = mTextPaint.setFontVariationSettings(fontVariationSettings);
 
-        if (mLayout != null) {
+        if (effective && mLayout != null) {
             nullLayouts();
             requestLayout();
             invalidate();
         }
+        return effective;
     }
 
     /**
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 0cdc74f..d0b07d0 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -91,6 +91,24 @@
     Typeface::setDefault(face);
 }
 
+static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
+    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+    const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
+    const size_t length = tagSet.size();
+    if (length == 0) {
+        return nullptr;
+    }
+    std::vector<jint> tagVec(length);
+    int index = 0;
+    for (const auto& tag : tagSet) {
+        tagVec[index++] = tag;
+    }
+    std::sort(tagVec.begin(), tagVec.end());
+    const jintArray result = env->NewIntArray(length);
+    env->SetIntArrayRegion(result, 0, length, tagVec.data());
+    return result;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static const JNINativeMethod gTypefaceMethods[] = {
@@ -103,6 +121,7 @@
     { "nativeCreateFromArray",    "([J)J",
                                            (void*)Typeface_createFromArray },
     { "nativeSetDefault",         "(J)V",   (void*)Typeface_setDefault },
+    { "nativeGetSupportedAxes",   "(J)[I",  (void*)Typeface_getSupportedAxes },
 };
 
 int register_android_graphics_Typeface(JNIEnv* env)
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 5d6aa8a..f4bf079 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -19,7 +19,9 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Size;
+import android.graphics.FontListParser;
 import android.os.LocaleList;
+import android.text.FontConfig;
 import android.text.GraphicsOperations;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -30,6 +32,9 @@
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Locale;
 
@@ -1531,21 +1536,46 @@
     /**
      * Set font variation settings.
      *
+     * This function does nothing if none of the settings is applicable to underlying font files.
+     *
      * @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8"
      *
      * @see #getFontVariationSettings()
      *
      * @param settings the font variation settings. You can pass null or empty string as no
      *                 variation settings.
+     * @return true if the given settings is effective to at least one font file underlying this
+     *         typeface. This function also returns true for empty settings string. Otherwise
+     *         returns false
      */
-    public void setFontVariationSettings(String settings) {
+    public boolean setFontVariationSettings(String settings) {
         settings = TextUtils.nullIfEmpty(settings);
         if (settings == mFontVariationSettings
                 || (settings != null && settings.equals(mFontVariationSettings))) {
-            return;
+            return true;
+        }
+
+        if (settings == null || settings.length() == 0) {
+            mFontVariationSettings = null;
+            setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface,
+                      Collections.emptyList()));
+            return true;
+        }
+
+        final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(settings);
+        final ArrayList<FontConfig.Axis> filteredAxes = new ArrayList<FontConfig.Axis>();
+        for (int i = 0; i < axes.size(); ++i) {
+            final FontConfig.Axis axis = axes.get(i);
+            if (mTypeface.isSupportedAxes(axis.getTag())) {
+                filteredAxes.add(axis);
+            }
+        }
+        if (filteredAxes.isEmpty()) {
+            return false;
         }
         mFontVariationSettings = settings;
-        setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, settings));
+        setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, filteredAxes));
+        return true;
     }
 
     /**
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 3416401..8511c1f 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -53,6 +53,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -116,6 +117,9 @@
 
     private int mStyle = 0;
 
+    private int[] mSupportedAxes;
+    private static final int[] EMPTY_AXES = {};
+
     private static void setDefault(Typeface t) {
         sDefaultTypeface = t;
         nativeSetDefault(t.native_instance);
@@ -492,10 +496,8 @@
 
     /** @hide */
     public static Typeface createFromTypefaceWithVariation(Typeface family,
-            String fontVariationSettings) {
+            List<FontConfig.Axis> axes) {
         final long ni = family == null ? 0 : family.native_instance;
-        ArrayList<FontConfig.Axis> axes =
-                FontListParser.parseFontVariationSettings(fontVariationSettings);
         return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
     }
 
@@ -788,6 +790,21 @@
         return result;
     }
 
+    /** @hide */
+    public boolean isSupportedAxes(int axis) {
+        if (mSupportedAxes == null) {
+            synchronized (this) {
+                if (mSupportedAxes == null) {
+                    mSupportedAxes = nativeGetSupportedAxes(native_instance);
+                    if (mSupportedAxes == null) {
+                        mSupportedAxes = EMPTY_AXES;
+                    }
+                }
+            }
+        }
+        return Arrays.binarySearch(mSupportedAxes, axis) > 0;
+    }
+
     private static native long nativeCreateFromTypeface(long native_instance, int style);
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontConfig.Axis> axes);
@@ -796,4 +813,5 @@
     private static native int  nativeGetStyle(long native_instance);
     private static native long nativeCreateFromArray(long[] familyArray);
     private static native void nativeSetDefault(long native_instance);
+    private static native int[] nativeGetSupportedAxes(long native_instance);
 }