From 8c2c82d399fb500649fbd98e4c88c4a165e0543d Mon Sep 17 00:00:00 2001 From: Kevin Jeon Date: Tue, 5 Oct 2021 02:56:19 +0000 Subject: [PATCH] Discourage methods that use resource reflection This change adds the @Discouraged annotation to methods that access resources by name (getIdentifier() and getValue()). Users will be directed to retrieve resources by identifier instead. Bug: 202194091 Test: Checked that getIdentifier() and getValue() raise lint warnings. Change-Id: Ib69797bf9ccf9e336326a3925fb6409048b647ad --- core/api/current.txt | 4 ++-- core/java/android/content/res/Resources.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 78556671d34b7..277634d6d45df 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -13453,7 +13453,7 @@ package android.content.res { method public float getFloat(@DimenRes int); method @NonNull public android.graphics.Typeface getFont(@FontRes int) throws android.content.res.Resources.NotFoundException; method public float getFraction(@FractionRes int, int, int); - method public int getIdentifier(String, String, String); + method @Discouraged(message="Use of this function is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code. It is much more efficient to retrieve resources by identifier (e.g. `R.foo.bar`) than by name (e.g. `getIdentifier(\"bar\", \"foo\", null)`).") public int getIdentifier(String, String, String); method @NonNull public int[] getIntArray(@ArrayRes int) throws android.content.res.Resources.NotFoundException; method public int getInteger(@IntegerRes int) throws android.content.res.Resources.NotFoundException; method @NonNull public android.content.res.XmlResourceParser getLayout(@LayoutRes int) throws android.content.res.Resources.NotFoundException; @@ -13473,7 +13473,7 @@ package android.content.res { method public CharSequence getText(@StringRes int, CharSequence); method @NonNull public CharSequence[] getTextArray(@ArrayRes int) throws android.content.res.Resources.NotFoundException; method public void getValue(@AnyRes int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; - method public void getValue(String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; + method @Discouraged(message="Use of this function is discouraged because it makes internal calls to `getIdentifier()`, which uses resource reflection. Reflection makes it harder to perform build optimizations and compile-time verification of code. It is much more efficient to retrieve resource values by identifier (e.g. `getValue(R.foo.bar, outValue, true)`) than by name (e.g. `getValue(\"foo\", outvalue, true)`).") public void getValue(String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method public void getValueForDensity(@AnyRes int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException; method @NonNull public android.content.res.XmlResourceParser getXml(@XmlRes int) throws android.content.res.Resources.NotFoundException; method public final android.content.res.Resources.Theme newTheme(); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 12e41e299e162..a6f2e4083cb94 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -27,6 +27,7 @@ import android.annotation.BoolRes; import android.annotation.ColorInt; import android.annotation.ColorRes; import android.annotation.DimenRes; +import android.annotation.Discouraged; import android.annotation.DrawableRes; import android.annotation.FontRes; import android.annotation.FractionRes; @@ -1466,6 +1467,12 @@ public class Resources { * @throws NotFoundException Throws NotFoundException if the given ID does not exist. * */ + @Discouraged(message = "Use of this function is discouraged because it makes internal calls to " + + "`getIdentifier()`, which uses resource reflection. Reflection makes it " + + "harder to perform build optimizations and compile-time verification of " + + "code. It is much more efficient to retrieve resource values by " + + "identifier (e.g. `getValue(R.foo.bar, outValue, true)`) than by name " + + "(e.g. `getValue(\"foo\", outvalue, true)`).") public void getValue(String name, TypedValue outValue, boolean resolveRefs) throws NotFoundException { mResourcesImpl.getValue(name, outValue, resolveRefs); @@ -2198,6 +2205,11 @@ public class Resources { * @return int The associated resource identifier. Returns 0 if no such * resource was found. (0 is not a valid resource ID.) */ + @Discouraged(message = "Use of this function is discouraged because resource reflection makes " + + "it harder to perform build optimizations and compile-time " + + "verification of code. It is much more efficient to retrieve " + + "resources by identifier (e.g. `R.foo.bar`) than by name (e.g. " + + "`getIdentifier(\"bar\", \"foo\", null)`).") public int getIdentifier(String name, String defType, String defPackage) { return mResourcesImpl.getIdentifier(name, defType, defPackage); }