422 lines
17 KiB
Java
422 lines
17 KiB
Java
package androidx.core.content.res;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.ColorStateList;
|
|
import android.content.res.Configuration;
|
|
import android.content.res.Resources;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.util.Log;
|
|
import android.util.SparseArray;
|
|
import android.util.TypedValue;
|
|
import androidx.annotation.AnyRes;
|
|
import androidx.annotation.ColorInt;
|
|
import androidx.annotation.ColorRes;
|
|
import androidx.annotation.DimenRes;
|
|
import androidx.annotation.DrawableRes;
|
|
import androidx.annotation.FontRes;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.core.content.res.FontResourcesParserCompat;
|
|
import androidx.core.graphics.TypefaceCompat;
|
|
import androidx.core.util.ObjectsCompat;
|
|
import androidx.core.util.Preconditions;
|
|
import c.d.b.a.a;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.util.WeakHashMap;
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
public final class ResourcesCompat {
|
|
@AnyRes
|
|
public static final int ID_NULL = 0;
|
|
private static final String TAG = "ResourcesCompat";
|
|
private static final Object sColorStateCacheLock = new Object();
|
|
private static final WeakHashMap<ColorStateListCacheKey, SparseArray<ColorStateListCacheEntry>> sColorStateCaches = new WeakHashMap<>(0);
|
|
private static final ThreadLocal<TypedValue> sTempTypedValue = new ThreadLocal<>();
|
|
|
|
public static class ColorStateListCacheEntry {
|
|
public final Configuration mConfiguration;
|
|
public final ColorStateList mValue;
|
|
|
|
public ColorStateListCacheEntry(@NonNull ColorStateList colorStateList, @NonNull Configuration configuration) {
|
|
this.mValue = colorStateList;
|
|
this.mConfiguration = configuration;
|
|
}
|
|
}
|
|
|
|
public static final class ColorStateListCacheKey {
|
|
public final Resources mResources;
|
|
@Nullable
|
|
public final Resources.Theme mTheme;
|
|
|
|
public ColorStateListCacheKey(@NonNull Resources resources, @Nullable Resources.Theme theme) {
|
|
this.mResources = resources;
|
|
this.mTheme = theme;
|
|
}
|
|
|
|
public boolean equals(Object obj) {
|
|
if (this == obj) {
|
|
return true;
|
|
}
|
|
if (obj == null || ColorStateListCacheKey.class != obj.getClass()) {
|
|
return false;
|
|
}
|
|
ColorStateListCacheKey colorStateListCacheKey = (ColorStateListCacheKey) obj;
|
|
return this.mResources.equals(colorStateListCacheKey.mResources) && ObjectsCompat.equals(this.mTheme, colorStateListCacheKey.mTheme);
|
|
}
|
|
|
|
public int hashCode() {
|
|
return ObjectsCompat.hash(this.mResources, this.mTheme);
|
|
}
|
|
}
|
|
|
|
public static abstract class FontCallback {
|
|
|
|
/* renamed from: androidx.core.content.res.ResourcesCompat$FontCallback$1 reason: invalid class name */
|
|
public class AnonymousClass1 implements Runnable {
|
|
public final /* synthetic */ Typeface val$typeface;
|
|
|
|
public AnonymousClass1(Typeface typeface) {
|
|
this.val$typeface = typeface;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
FontCallback.this.onFontRetrieved(this.val$typeface);
|
|
}
|
|
}
|
|
|
|
/* renamed from: androidx.core.content.res.ResourcesCompat$FontCallback$2 reason: invalid class name */
|
|
public class AnonymousClass2 implements Runnable {
|
|
public final /* synthetic */ int val$reason;
|
|
|
|
public AnonymousClass2(int i) {
|
|
this.val$reason = i;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
FontCallback.this.onFontRetrievalFailed(this.val$reason);
|
|
}
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY})
|
|
public static Handler getHandler(@Nullable Handler handler) {
|
|
return handler == null ? new Handler(Looper.getMainLooper()) : handler;
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public final void callbackFailAsync(int i, @Nullable Handler handler) {
|
|
getHandler(handler).post(new AnonymousClass2(i));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public final void callbackSuccessAsync(Typeface typeface, @Nullable Handler handler) {
|
|
getHandler(handler).post(new AnonymousClass1(typeface));
|
|
}
|
|
|
|
public abstract void onFontRetrievalFailed(int i);
|
|
|
|
public abstract void onFontRetrieved(@NonNull Typeface typeface);
|
|
}
|
|
|
|
@RequiresApi(29)
|
|
public static class ImplApi29 {
|
|
private ImplApi29() {
|
|
}
|
|
|
|
public static float getFloat(@NonNull Resources resources, @DimenRes int i) {
|
|
return resources.getFloat(i);
|
|
}
|
|
}
|
|
|
|
public static final class ThemeCompat {
|
|
|
|
@RequiresApi(23)
|
|
public static class ImplApi23 {
|
|
private static Method sRebaseMethod;
|
|
private static boolean sRebaseMethodFetched;
|
|
private static final Object sRebaseMethodLock = new Object();
|
|
|
|
private ImplApi23() {
|
|
}
|
|
|
|
public static void rebase(@NonNull Resources.Theme theme) {
|
|
synchronized (sRebaseMethodLock) {
|
|
if (!sRebaseMethodFetched) {
|
|
try {
|
|
Method declaredMethod = Resources.Theme.class.getDeclaredMethod("rebase", new Class[0]);
|
|
sRebaseMethod = declaredMethod;
|
|
declaredMethod.setAccessible(true);
|
|
} catch (NoSuchMethodException e) {
|
|
Log.i(ResourcesCompat.TAG, "Failed to retrieve rebase() method", e);
|
|
}
|
|
sRebaseMethodFetched = true;
|
|
}
|
|
Method method = sRebaseMethod;
|
|
if (method != null) {
|
|
try {
|
|
method.invoke(theme, new Object[0]);
|
|
} catch (IllegalAccessException | InvocationTargetException e2) {
|
|
Log.i(ResourcesCompat.TAG, "Failed to invoke rebase() method via reflection", e2);
|
|
sRebaseMethod = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@RequiresApi(29)
|
|
public static class ImplApi29 {
|
|
private ImplApi29() {
|
|
}
|
|
|
|
public static void rebase(@NonNull Resources.Theme theme) {
|
|
theme.rebase();
|
|
}
|
|
}
|
|
|
|
private ThemeCompat() {
|
|
}
|
|
|
|
public static void rebase(@NonNull Resources.Theme theme) {
|
|
int i = Build.VERSION.SDK_INT;
|
|
if (i >= 29) {
|
|
ImplApi29.rebase(theme);
|
|
} else if (i >= 23) {
|
|
ImplApi23.rebase(theme);
|
|
}
|
|
}
|
|
}
|
|
|
|
private ResourcesCompat() {
|
|
}
|
|
|
|
private static void addColorStateListToCache(@NonNull ColorStateListCacheKey colorStateListCacheKey, @ColorRes int i, @NonNull ColorStateList colorStateList) {
|
|
synchronized (sColorStateCacheLock) {
|
|
WeakHashMap<ColorStateListCacheKey, SparseArray<ColorStateListCacheEntry>> weakHashMap = sColorStateCaches;
|
|
SparseArray<ColorStateListCacheEntry> sparseArray = weakHashMap.get(colorStateListCacheKey);
|
|
if (sparseArray == null) {
|
|
sparseArray = new SparseArray<>();
|
|
weakHashMap.put(colorStateListCacheKey, sparseArray);
|
|
}
|
|
sparseArray.append(i, new ColorStateListCacheEntry(colorStateList, colorStateListCacheKey.mResources.getConfiguration()));
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
private static ColorStateList getCachedColorStateList(@NonNull ColorStateListCacheKey colorStateListCacheKey, @ColorRes int i) {
|
|
ColorStateListCacheEntry colorStateListCacheEntry;
|
|
synchronized (sColorStateCacheLock) {
|
|
SparseArray<ColorStateListCacheEntry> sparseArray = sColorStateCaches.get(colorStateListCacheKey);
|
|
if (!(sparseArray == null || sparseArray.size() <= 0 || (colorStateListCacheEntry = sparseArray.get(i)) == null)) {
|
|
if (colorStateListCacheEntry.mConfiguration.equals(colorStateListCacheKey.mResources.getConfiguration())) {
|
|
return colorStateListCacheEntry.mValue;
|
|
}
|
|
sparseArray.remove(i);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public static Typeface getCachedFont(@NonNull Context context, @FontRes int i) throws Resources.NotFoundException {
|
|
if (context.isRestricted()) {
|
|
return null;
|
|
}
|
|
return loadFont(context, i, new TypedValue(), 0, null, null, false, true);
|
|
}
|
|
|
|
@ColorInt
|
|
public static int getColor(@NonNull Resources resources, @ColorRes int i, @Nullable Resources.Theme theme) throws Resources.NotFoundException {
|
|
return Build.VERSION.SDK_INT >= 23 ? resources.getColor(i, theme) : resources.getColor(i);
|
|
}
|
|
|
|
@Nullable
|
|
public static ColorStateList getColorStateList(@NonNull Resources resources, @ColorRes int i, @Nullable Resources.Theme theme) throws Resources.NotFoundException {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
return resources.getColorStateList(i, theme);
|
|
}
|
|
ColorStateListCacheKey colorStateListCacheKey = new ColorStateListCacheKey(resources, theme);
|
|
ColorStateList cachedColorStateList = getCachedColorStateList(colorStateListCacheKey, i);
|
|
if (cachedColorStateList != null) {
|
|
return cachedColorStateList;
|
|
}
|
|
ColorStateList inflateColorStateList = inflateColorStateList(resources, i, theme);
|
|
if (inflateColorStateList == null) {
|
|
return resources.getColorStateList(i);
|
|
}
|
|
addColorStateListToCache(colorStateListCacheKey, i, inflateColorStateList);
|
|
return inflateColorStateList;
|
|
}
|
|
|
|
@Nullable
|
|
public static Drawable getDrawable(@NonNull Resources resources, @DrawableRes int i, @Nullable Resources.Theme theme) throws Resources.NotFoundException {
|
|
return resources.getDrawable(i, theme);
|
|
}
|
|
|
|
@Nullable
|
|
public static Drawable getDrawableForDensity(@NonNull Resources resources, @DrawableRes int i, int i2, @Nullable Resources.Theme theme) throws Resources.NotFoundException {
|
|
return resources.getDrawableForDensity(i, i2, theme);
|
|
}
|
|
|
|
public static float getFloat(@NonNull Resources resources, @DimenRes int i) {
|
|
if (Build.VERSION.SDK_INT >= 29) {
|
|
return ImplApi29.getFloat(resources, i);
|
|
}
|
|
TypedValue typedValue = getTypedValue();
|
|
resources.getValue(i, typedValue, true);
|
|
if (typedValue.type == 4) {
|
|
return typedValue.getFloat();
|
|
}
|
|
StringBuilder P = a.P("Resource ID #0x");
|
|
P.append(Integer.toHexString(i));
|
|
P.append(" type #0x");
|
|
P.append(Integer.toHexString(typedValue.type));
|
|
P.append(" is not valid");
|
|
throw new Resources.NotFoundException(P.toString());
|
|
}
|
|
|
|
@Nullable
|
|
public static Typeface getFont(@NonNull Context context, @FontRes int i) throws Resources.NotFoundException {
|
|
if (context.isRestricted()) {
|
|
return null;
|
|
}
|
|
return loadFont(context, i, new TypedValue(), 0, null, null, false, false);
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP_PREFIX})
|
|
public static Typeface getFont(@NonNull Context context, @FontRes int i, TypedValue typedValue, int i2, @Nullable FontCallback fontCallback) throws Resources.NotFoundException {
|
|
if (context.isRestricted()) {
|
|
return null;
|
|
}
|
|
return loadFont(context, i, typedValue, i2, fontCallback, null, true, false);
|
|
}
|
|
|
|
public static void getFont(@NonNull Context context, @FontRes int i, @NonNull FontCallback fontCallback, @Nullable Handler handler) throws Resources.NotFoundException {
|
|
Preconditions.checkNotNull(fontCallback);
|
|
if (context.isRestricted()) {
|
|
fontCallback.callbackFailAsync(-4, handler);
|
|
} else {
|
|
loadFont(context, i, new TypedValue(), 0, fontCallback, handler, false, false);
|
|
}
|
|
}
|
|
|
|
@NonNull
|
|
private static TypedValue getTypedValue() {
|
|
ThreadLocal<TypedValue> threadLocal = sTempTypedValue;
|
|
TypedValue typedValue = threadLocal.get();
|
|
if (typedValue != null) {
|
|
return typedValue;
|
|
}
|
|
TypedValue typedValue2 = new TypedValue();
|
|
threadLocal.set(typedValue2);
|
|
return typedValue2;
|
|
}
|
|
|
|
@Nullable
|
|
private static ColorStateList inflateColorStateList(Resources resources, int i, @Nullable Resources.Theme theme) {
|
|
if (isColorInt(resources, i)) {
|
|
return null;
|
|
}
|
|
try {
|
|
return ColorStateListInflaterCompat.createFromXml(resources, resources.getXml(i), theme);
|
|
} catch (Exception e) {
|
|
Log.e(TAG, "Failed to inflate ColorStateList, leaving it to the framework", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static boolean isColorInt(@NonNull Resources resources, @ColorRes int i) {
|
|
TypedValue typedValue = getTypedValue();
|
|
resources.getValue(i, typedValue, true);
|
|
int i2 = typedValue.type;
|
|
return i2 >= 28 && i2 <= 31;
|
|
}
|
|
|
|
private static Typeface loadFont(@NonNull Context context, int i, TypedValue typedValue, int i2, @Nullable FontCallback fontCallback, @Nullable Handler handler, boolean z2, boolean z3) {
|
|
Resources resources = context.getResources();
|
|
resources.getValue(i, typedValue, true);
|
|
Typeface loadFont = loadFont(context, resources, typedValue, i, i2, fontCallback, handler, z2, z3);
|
|
if (loadFont != null || fontCallback != null || z3) {
|
|
return loadFont;
|
|
}
|
|
StringBuilder P = a.P("Font resource ID #0x");
|
|
P.append(Integer.toHexString(i));
|
|
P.append(" could not be retrieved.");
|
|
throw new Resources.NotFoundException(P.toString());
|
|
}
|
|
|
|
/* JADX WARNING: Removed duplicated region for block: B:36:0x00a7 */
|
|
private static Typeface loadFont(@NonNull Context context, Resources resources, TypedValue typedValue, int i, int i2, @Nullable FontCallback fontCallback, @Nullable Handler handler, boolean z2, boolean z3) {
|
|
CharSequence charSequence = typedValue.string;
|
|
if (charSequence != null) {
|
|
String charSequence2 = charSequence.toString();
|
|
if (!charSequence2.startsWith("res/")) {
|
|
if (fontCallback != null) {
|
|
fontCallback.callbackFailAsync(-3, handler);
|
|
}
|
|
return null;
|
|
}
|
|
Typeface findFromCache = TypefaceCompat.findFromCache(resources, i, i2);
|
|
if (findFromCache != null) {
|
|
if (fontCallback != null) {
|
|
fontCallback.callbackSuccessAsync(findFromCache, handler);
|
|
}
|
|
return findFromCache;
|
|
} else if (z3) {
|
|
return null;
|
|
} else {
|
|
try {
|
|
if (charSequence2.toLowerCase().endsWith(".xml")) {
|
|
FontResourcesParserCompat.FamilyResourceEntry parse = FontResourcesParserCompat.parse(resources.getXml(i), resources);
|
|
if (parse != null) {
|
|
return TypefaceCompat.createFromResourcesFamilyXml(context, parse, resources, i, i2, fontCallback, handler, z2);
|
|
}
|
|
Log.e(TAG, "Failed to find font-family tag");
|
|
if (fontCallback != null) {
|
|
fontCallback.callbackFailAsync(-3, handler);
|
|
}
|
|
return null;
|
|
}
|
|
Typeface createFromResourcesFontFile = TypefaceCompat.createFromResourcesFontFile(context, resources, i, charSequence2, i2);
|
|
if (fontCallback != null) {
|
|
if (createFromResourcesFontFile != null) {
|
|
fontCallback.callbackSuccessAsync(createFromResourcesFontFile, handler);
|
|
} else {
|
|
fontCallback.callbackFailAsync(-3, handler);
|
|
}
|
|
}
|
|
return createFromResourcesFontFile;
|
|
} catch (XmlPullParserException e) {
|
|
Log.e(TAG, "Failed to parse xml resource " + charSequence2, e);
|
|
if (fontCallback != null) {
|
|
fontCallback.callbackFailAsync(-3, handler);
|
|
}
|
|
return null;
|
|
} catch (IOException e2) {
|
|
Log.e(TAG, "Failed to read xml resource " + charSequence2, e2);
|
|
if (fontCallback != null) {
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
} else {
|
|
StringBuilder P = a.P("Resource \"");
|
|
P.append(resources.getResourceName(i));
|
|
P.append("\" (");
|
|
P.append(Integer.toHexString(i));
|
|
P.append(") is not a Font: ");
|
|
P.append(typedValue);
|
|
throw new Resources.NotFoundException(P.toString());
|
|
}
|
|
}
|
|
}
|