summaryrefslogtreecommitdiff
path: root/SafetyCenter
diff options
context:
space:
mode:
authorElliot Sisteron <elliotsisteron@google.com>2023-06-08 10:36:53 +0000
committerElliot Sisteron <elliotsisteron@google.com>2023-06-08 16:13:49 +0000
commitfaf20cf1ac1f2a19221ce84a0dc9d337f2dd598a (patch)
treed01b078f1974bbbb8f9f402c65be26775a4bbbd3 /SafetyCenter
parent12ee4e41001227322fa0859d6487a6e2b1848e7e (diff)
downloadPermission-faf20cf1ac1f2a19221ce84a0dc9d337f2dd598a.tar.gz
Further refactoring of SafetyCenterResourcesContext.
Stop making it implement ContextWrapper, that's error-prone as it implies it has the Context from the resources APK as a base when in fact the base is the context passed in; and methods are overridden only partially. Also increase test coverage. Bug: 283100177 Test: atest CtsSafetyCenterTestCases Relnote: N/A Change-Id: I2925921de3de01633beacbbe713d46e9522f003b
Diffstat (limited to 'SafetyCenter')
-rw-r--r--SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java243
-rw-r--r--SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt1
-rw-r--r--SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt300
3 files changed, 366 insertions, 178 deletions
diff --git a/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java b/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java
index 215e0f6d7..25455dc7a 100644
--- a/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java
+++ b/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java
@@ -19,11 +19,9 @@ package com.android.safetycenter.resources;
import static java.util.Objects.requireNonNull;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -39,12 +37,17 @@ import java.io.InputStream;
import java.util.List;
/**
- * Wrapper for a base context to expose Safety Center resources that need to be fetched from a
- * dedicated APK.
+ * A class to access Safety Center resources that need to be fetched from a dedicated APK.
*
- * <p>This class isn't thread safe. Thread safety must be handled by the caller.
+ * <p>You must check whether Safety Center is enabled or the value returned by {@link #init()} prior
+ * to interacting with this class. Failure to do so may cause an {@link IllegalStateException} if
+ * the resources APK cannot be accessed.
+ *
+ * <p>This class isn't thread safe. Thread safety must be handled by the caller, or this may cause
+ * the resources APK {@link Context} to be initialized multiple times.
*/
-public final class SafetyCenterResourcesContext extends ContextWrapper {
+public final class SafetyCenterResourcesContext {
+
private static final String TAG = "SafetyCenterResContext";
/** Intent action that is used to identify the Safety Center resources APK */
@@ -63,15 +66,14 @@ public final class SafetyCenterResourcesContext extends ContextWrapper {
/** Raw XML config resource name */
private static final String CONFIG_NAME = "safety_center_config";
+ private final Context mContext;
+
/** Intent action that is used to identify the Safety Center resources APK */
private final String mResourcesApkAction;
/** The path where the Safety Center resources APK is expected to be installed */
private final String mResourcesApkPath;
- /** Raw XML config resource name */
- private final String mConfigName;
-
/** Specific flags used for retrieving resolve info. */
private final int mFlags;
@@ -81,36 +83,33 @@ public final class SafetyCenterResourcesContext extends ContextWrapper {
*/
private final boolean mShouldFallbackIfNamedResourceNotFound;
- // Cached context from the resources APK
+ // Cached context from the resources APK.
@Nullable private Context mResourcesApkContext;
- public SafetyCenterResourcesContext(Context contextBase) {
- this(contextBase, /* shouldFallbackIfNamedResourceNotFound */ true);
+ public SafetyCenterResourcesContext(Context context) {
+ this(context, /* shouldFallbackIfNamedResourceNotFound */ true);
}
private SafetyCenterResourcesContext(
- Context contextBase, boolean shouldFallbackIfNamedResourceNotFound) {
+ Context context, boolean shouldFallbackIfNamedResourceNotFound) {
this(
- contextBase,
+ context,
RESOURCES_APK_ACTION,
APEX_MODULE_PATH,
- CONFIG_NAME,
PackageManager.MATCH_SYSTEM_ONLY,
shouldFallbackIfNamedResourceNotFound);
}
@VisibleForTesting
SafetyCenterResourcesContext(
- Context contextBase,
+ Context context,
String resourcesApkAction,
String resourcesApkPath,
- String configName,
int flags,
boolean shouldFallbackIfNamedResourceNotFound) {
- super(contextBase);
+ mContext = requireNonNull(context);
mResourcesApkAction = requireNonNull(resourcesApkAction);
mResourcesApkPath = requireNonNull(resourcesApkPath);
- mConfigName = requireNonNull(configName);
mFlags = flags;
mShouldFallbackIfNamedResourceNotFound = shouldFallbackIfNamedResourceNotFound;
}
@@ -132,25 +131,33 @@ public final class SafetyCenterResourcesContext extends ContextWrapper {
* explicitly.
*/
public boolean init() {
- return getResourcesApkContext() != null;
+ mResourcesApkContext = loadResourcesApkContext();
+ return mResourcesApkContext != null;
}
- /** Gets the {@link Context} of the Safety Center resources APK. */
- @VisibleForTesting
- @Nullable
- Context getResourcesApkContext() {
+ /**
+ * Returns the {@link Context} of the Safety Center resources APK.
+ *
+ * <p>Throws an {@link IllegalStateException} if the resources APK is not available
+ */
+ public Context getResourcesApkContext() {
if (mResourcesApkContext != null) {
return mResourcesApkContext;
}
mResourcesApkContext = loadResourcesApkContext();
+ if (mResourcesApkContext == null) {
+ throw new IllegalStateException("Resources APK context not found");
+ }
+
return mResourcesApkContext;
}
@Nullable
private Context loadResourcesApkContext() {
List<ResolveInfo> resolveInfos =
- getPackageManager().queryIntentActivities(new Intent(mResourcesApkAction), mFlags);
+ mContext.getPackageManager()
+ .queryIntentActivities(new Intent(mResourcesApkAction), mFlags);
if (resolveInfos.size() > 1) {
// multiple apps found, log a warning, but continue
@@ -197,183 +204,153 @@ public final class SafetyCenterResourcesContext extends ContextWrapper {
@Nullable
private Context getPackageContext(String packageName) {
try {
- return createPackageContext(packageName, 0);
+ return mContext.createPackageContext(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to load package context for: " + packageName, e);
}
return null;
}
+ /** Calls {@link Context#getResources()} for the resources APK {@link Context}. */
+ public Resources getResources() {
+ return getResourcesApkContext().getResources();
+ }
+
/**
- * Gets the raw XML resource representing the Safety Center configuration from the Safety Center
- * resources APK.
+ * Returns the raw XML resource representing the Safety Center configuration file from the
+ * Safety Center resources APK.
*/
@Nullable
public InputStream getSafetyCenterConfig() {
- int id = getResId(mConfigName, "raw");
- if (id == Resources.ID_NULL) {
- return null;
- }
- return getResources().openRawResource(id);
+ return getSafetyCenterConfig(CONFIG_NAME);
}
- /**
- * Returns an optional {@link String} resource from the given {@code stringId}.
- *
- * <p>Returns {@code null} if {@code stringId} is equal to {@link Resources#ID_NULL}. Otherwise,
- * throws a {@link Resources.NotFoundException} if the resource cannot be accessed.
- */
+ @VisibleForTesting
@Nullable
- public String getOptionalString(@StringRes int stringId) {
- if (stringId == Resources.ID_NULL) {
+ InputStream getSafetyCenterConfig(String configName) {
+ int id = getResIdAndMaybeThrowIfNull(configName, "raw");
+ if (id == Resources.ID_NULL) {
return null;
}
- return getString(stringId);
+ return getResources().openRawResource(id);
}
- /** Same as {@link #getOptionalString(int)} but with the given {@code formatArgs}. */
- @Nullable
- public String getOptionalString(@StringRes int stringId, Object... formatArgs) {
- if (stringId == Resources.ID_NULL) {
- return null;
- }
- return getString(stringId, formatArgs);
+ /** Calls {@link Context#getString(int)} for the resources APK {@link Context}. */
+ public String getString(@StringRes int stringId) {
+ return getResourcesApkContext().getString(stringId);
}
- /** Same as {@link #getOptionalString(int)} but using the string name rather than ID. */
- @Nullable
- public String getOptionalStringByName(String name) {
- return getOptionalString(getResId(name, "string"));
+ /** Same as {@link #getString(int)} but with the given {@code formatArgs}. */
+ public String getString(@StringRes int stringId, Object... formatArgs) {
+ return getResourcesApkContext().getString(stringId, formatArgs);
}
/**
- * Gets a string resource by name from the Safety Center resources APK, and returns an empty
- * string if the resource does not exist (or throws a {@link Resources.NotFoundException} if
- * {@link #mShouldFallbackIfNamedResourceNotFound} is {@code false}).
+ * Returns the {@link String} with the given resource name.
+ *
+ * <p>If the {@link String} cannot be accessed, returns {@code ""} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
*/
public String getStringByName(String name) {
- int id = getResId(name, "string");
- return maybeFallbackIfNamedResourceIsNull(name, getOptionalString(id));
+ int resId = getResIdAndMaybeThrowIfNull(name, "string");
+ if (resId == Resources.ID_NULL) {
+ return "";
+ }
+ return getString(resId);
}
/** Same as {@link #getStringByName(String)} but with the given {@code formatArgs}. */
public String getStringByName(String name, Object... formatArgs) {
- int id = getResId(name, "string");
- return maybeFallbackIfNamedResourceIsNull(name, getOptionalString(id, formatArgs));
- }
-
- /** Retrieve assets held in the Safety Center resources APK. */
- @Override
- @Nullable
- public AssetManager getAssets() {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext == null) {
- return null;
+ int resId = getResIdAndMaybeThrowIfNull(name, "string");
+ if (resId == Resources.ID_NULL) {
+ return "";
}
- return resourcesApkContext.getAssets();
+ return getString(resId, formatArgs);
}
- /** Retrieve resources held in the Safety Center resources APK. */
- @Override
+ /**
+ * Returns an optional {@link String} resource with the given {@code stringId}.
+ *
+ * <p>Returns {@code null} if {@code stringId} is equal to {@link Resources#ID_NULL}. Otherwise,
+ * throws a {@link Resources.NotFoundException}.
+ */
@Nullable
- public Resources getResources() {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext == null) {
+ public String getOptionalString(@StringRes int stringId) {
+ if (stringId == Resources.ID_NULL) {
return null;
}
- return resourcesApkContext.getResources();
+ return getString(stringId);
}
- /** Retrieve theme held in the Safety Center resources APK. */
- @Override
+ /** Same as {@link #getOptionalString(int)} but with the given resource name rather than ID. */
@Nullable
- public Resources.Theme getTheme() {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext == null) {
- return null;
- }
- return resourcesApkContext.getTheme();
+ public String getOptionalStringByName(String name) {
+ return getOptionalString(getResId(name, "string"));
}
/**
- * Gets a drawable resource by name from the Safety Center resources APK. Returns a null
- * drawable if the resource does not exist (or throws a {@link Resources.NotFoundException} if
- * {@link #mShouldFallbackIfNamedResourceNotFound} is {@code false}).
+ * Returns the {@link Drawable} with the given resource name.
+ *
+ * <p>If the {@link Drawable} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
*
- * @param name the identifier for this drawable resource
* @param theme the theme used to style the drawable attributes, may be {@code null}
*/
@Nullable
public Drawable getDrawableByName(String name, @Nullable Resources.Theme theme) {
- int resId = getResId(name, "drawable");
- if (resId != Resources.ID_NULL) {
- return getResources().getDrawable(resId, theme);
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
+ int resId = getResIdAndMaybeThrowIfNull(name, "drawable");
+ if (resId == Resources.ID_NULL) {
+ return null;
}
-
- Log.w(TAG, "Drawable resource " + name + " not found");
- return null;
+ return getResources().getDrawable(resId, theme);
}
/**
- * Returns an {@link Icon} instance containing a drawable with the given name. If no such
- * drawable exists, returns {@code null} or throws {@link Resources.NotFoundException}.
+ * Returns an {@link Icon} containing the {@link Drawable} with the given resource name.
+ *
+ * <p>If the {@link Drawable} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
*/
@Nullable
public Icon getIconByDrawableName(String name) {
- int resId = getResId(name, "drawable");
- if (resId != Resources.ID_NULL) {
- return Icon.createWithResource(getResourcesApkContext().getPackageName(), resId);
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
+ int resId = getResIdAndMaybeThrowIfNull(name, "drawable");
+ if (resId == Resources.ID_NULL) {
+ return null;
}
-
- Log.w(TAG, "Drawable resource " + name + " not found");
- return null;
+ return Icon.createWithResource(getResourcesApkContext().getPackageName(), resId);
}
- /** Gets a color by resource name */
+ /**
+ * Returns the {@link ColorInt} with the given resource name.
+ *
+ * <p>If the {@link ColorInt} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
+ */
@ColorInt
@Nullable
public Integer getColorByName(String name) {
- int resId = getResId(name, "color");
- if (resId != Resources.ID_NULL) {
- return getResources().getColor(resId, getTheme());
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
+ int resId = getResIdAndMaybeThrowIfNull(name, "color");
+ if (resId == Resources.ID_NULL) {
+ return null;
}
-
- Log.w(TAG, "Color resource " + name + " not found");
- return null;
+ return getResources().getColor(resId, getResourcesApkContext().getTheme());
}
- private String maybeFallbackIfNamedResourceIsNull(String name, @Nullable String value) {
- if (value != null) {
- return value;
+ private int getResIdAndMaybeThrowIfNull(String name, String type) {
+ int resId = getResId(name, type);
+ if (resId != Resources.ID_NULL) {
+ return resId;
}
if (!mShouldFallbackIfNamedResourceNotFound) {
throw new Resources.NotFoundException();
}
- Log.w(TAG, "String resource " + name + " not found");
- return "";
+ Log.w(TAG, "Named " + type + " resource: " + name + " not found");
+ return resId;
}
private int getResId(String name, String type) {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext == null) {
- return Resources.ID_NULL;
- }
// TODO(b/227738283): profile the performance of this operation and consider adding caching
// or finding some alternative solution.
- return resourcesApkContext
- .getResources()
- .getIdentifier(name, type, resourcesApkContext.getPackageName());
+ return getResources().getIdentifier(name, type, getResourcesApkContext().getPackageName());
}
}
diff --git a/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt b/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt
new file mode 100644
index 000000000..3b1246497
--- /dev/null
+++ b/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt
@@ -0,0 +1 @@
+TEST \ No newline at end of file
diff --git a/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt b/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt
index c7905ea47..33ff7543e 100644
--- a/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt
+++ b/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt
@@ -22,6 +22,7 @@ import android.content.res.Resources
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
+import java.lang.IllegalStateException
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
@@ -31,65 +32,172 @@ class SafetyCenterResourcesContextTest {
private val context: Context = getApplicationContext()
@Test
- fun validDataWithValidInputs() {
+ fun init_withValidInputs_returnsTrue() {
val resourcesContext = createNewResourcesContext()
- val resourcesApkContext = resourcesContext.resourcesApkContext
- assertThat(resourcesApkContext).isNotNull()
- assertThat(resourcesApkContext!!.packageName).isEqualTo(RESOURCES_APK_PKG_NAME)
+ val initialized = resourcesContext.init()
- val configContent =
- resourcesContext.safetyCenterConfig?.bufferedReader().use { it?.readText() }
+ assertThat(initialized).isTrue()
+ }
- assertThat(configContent).isEqualTo(CONFIG_CONTENT)
- assertThat(resourcesContext.assets).isNotNull()
- assertThat(resourcesContext.resources).isNotNull()
- assertThat(resourcesContext.theme).isNotNull()
+ @Test
+ fun init_withWrongAction_returnsFalse() {
+ val resourcesContext = createNewResourcesContext(resourcesApkAction = "wrong")
+
+ val initialized = resourcesContext.init()
+
+ assertThat(initialized).isFalse()
+ }
+
+ @Test
+ fun init_withWrongPath_returnsFalse() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkPath = "/apex/com.android.permission")
+
+ val initialized = resourcesContext.init()
+
+ assertThat(initialized).isFalse()
+ }
+
+ @Test
+ fun init_withWrongFlags_returnsFalse() {
+ val resourcesContext = createNewResourcesContext(flags = PackageManager.MATCH_SYSTEM_ONLY)
+
+ val initialized = resourcesContext.init()
+
+ assertThat(initialized).isFalse()
}
@Test
- fun nullDataWithWrongAction() {
+ fun getResourcesApkContext_withValidInputs_returnsResourcesApkContext() {
+ val resourcesContext = createNewResourcesContext()
+
+ val resourcesApkContext = resourcesContext.resourcesApkContext
+
+ assertThat(resourcesApkContext.packageName).isEqualTo(RESOURCES_APK_PKG_NAME)
+ }
+
+ @Test
+ fun getResourcesApkContext_withWrongAction_throws() {
val resourcesContext = createNewResourcesContext(resourcesApkAction = "wrong")
- assertThat(resourcesContext.resourcesApkContext).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
+ assertFailsWith(IllegalStateException::class) { resourcesContext.resourcesApkContext }
}
@Test
- fun nullDataWithWrongPath() {
+ fun getResourcesApkContext_withWrongPath_throws() {
val resourcesContext =
createNewResourcesContext(resourcesApkPath = "/apex/com.android.permission")
- assertThat(resourcesContext.resourcesApkContext).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
+ assertFailsWith(IllegalStateException::class) { resourcesContext.resourcesApkContext }
}
@Test
- fun nullDataWithWrongFlag() {
+ fun getResourcesApkContext_withWrongFlags_throws() {
val resourcesContext = createNewResourcesContext(flags = PackageManager.MATCH_SYSTEM_ONLY)
- assertThat(resourcesContext.resourcesApkContext).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
+ assertFailsWith(IllegalStateException::class) { resourcesContext.resourcesApkContext }
+ }
+
+ @Test
+ fun getResources_withValidInputs_returnsResourcesApkContextResources() {
+ val resourcesContext = createNewResourcesContext()
+
+ val resources = resourcesContext.resources
+
+ assertThat(resources).isEqualTo(resourcesContext.resourcesApkContext.resources)
+ }
+
+ @Test
+ fun getResources_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) { resourcesContext.resources }
+ }
+
+ @Test
+ fun getSafetyCenterConfig_withValidInputs_returnsConfigContent() {
+ val resourcesContext = createNewResourcesContext()
+
+ val config = resourcesContext.safetyCenterConfig
+ val configContent = config?.bufferedReader().use { it?.readText() }
+
+ assertThat(config).isNotNull()
+ assertThat(configContent).isEqualTo(CONFIG_CONTENT)
+ }
+
+ @Test
+ fun getSafetyCenterConfig_anotherValidConfigName_returnsConfigContent() {
+ val resourcesContext = createNewResourcesContext()
+
+ val config = resourcesContext.getSafetyCenterConfig(CONFIG_NAME)
+ val configContent = config?.bufferedReader().use { it?.readText() }
+
+ assertThat(config).isNotNull()
+ assertThat(configContent).isEqualTo(CONFIG_CONTENT)
+ }
+
+ @Test
+ fun getSafetyCenterConfig_invalidConfigNameWithFallback_returnsNull() {
+ val resourcesContext = createNewResourcesContext(fallback = true)
+
+ assertThat(resourcesContext.getSafetyCenterConfig("wrong")).isNull()
+ }
+
+ @Test
+ fun getSafetyCenterConfig_invalidConfigNameWithoutFallback_throws() {
+ val resourcesContext = createNewResourcesContext(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesContext.getSafetyCenterConfig("wrong")
+ }
+ }
+
+ @Test
+ fun getSafetyCenterConfig_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) { resourcesContext.safetyCenterConfig }
+ }
+
+ @Test
+ fun getString_validString_returnsString() {
+ val resourcesContext = createNewResourcesContext()
+
+ val ok = resourcesContext.getString(android.R.string.ok)
+
+ assertThat(ok).isEqualTo("OK")
+ }
+
+ @Test
+ fun getString_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getString(android.R.string.ok)
+ }
+ }
+
+ @Test
+ fun getStringWithFormatArgs_validString_returnsString() {
+ val resourcesContext = createNewResourcesContext()
+
+ val ok = resourcesContext.getString(android.R.string.ok, "")
+
+ assertThat(ok).isEqualTo("OK")
}
@Test
- fun nullConfigWithWrongConfigName() {
- val resourcesContext = createNewResourcesContext(configName = "wrong")
+ fun getStringWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
- assertThat(resourcesContext.resourcesApkContext).isNotNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNotNull()
- assertThat(resourcesContext.resources).isNotNull()
- assertThat(resourcesContext.theme).isNotNull()
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getString(android.R.string.ok, "")
+ }
}
@Test
@@ -116,6 +224,77 @@ class SafetyCenterResourcesContextTest {
}
@Test
+ fun getStringByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getStringByName("valid_string")
+ }
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_validString_returnsString() {
+ val resourcesContext = createNewResourcesContext()
+
+ assertThat(resourcesContext.getStringByName("valid_string", "")).isEqualTo("I exist!")
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_invalidStringWithFallback_returnsEmptyString() {
+ val resourcesContext = createNewResourcesContext(fallback = true)
+
+ assertThat(resourcesContext.getStringByName("invalid_string", "")).isEqualTo("")
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_invalidStringWithoutFallback_throws() {
+ val resourcesContext = createNewResourcesContext(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesContext.getStringByName("invalid_string", "")
+ }
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getStringByName("valid_string", "")
+ }
+ }
+
+ @Test
+ fun getOptionalString_validString_returnsString() {
+ val resourcesContext = createNewResourcesContext()
+
+ val ok = resourcesContext.getOptionalString(android.R.string.ok)
+
+ assertThat(ok).isEqualTo("OK")
+ }
+
+ @Test
+ fun getOptionalString_resourceIdNull_returnsNull() {
+ val resourcesContext = createNewResourcesContext()
+
+ val string = resourcesContext.getOptionalString(Resources.ID_NULL)
+
+ assertThat(string).isNull()
+ }
+
+ @Test
+ fun getOptionalString_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getOptionalString(android.R.string.ok)
+ }
+ }
+
+ @Test
fun getOptionalStringByName_validString_returnsString() {
val resourcesContext = createNewResourcesContext()
@@ -137,6 +316,16 @@ class SafetyCenterResourcesContextTest {
}
@Test
+ fun getOptionalStringByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getOptionalStringByName("valid_string")
+ }
+ }
+
+ @Test
fun getDrawableByName_validDrawable_returnsDrawable() {
val resourcesContext = createNewResourcesContext()
@@ -160,6 +349,16 @@ class SafetyCenterResourcesContextTest {
}
@Test
+ fun getDrawableByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getDrawableByName("valid_drawable", context.theme)
+ }
+ }
+
+ @Test
fun getIconByDrawableName_validDrawable_returnsIcon() {
val resourcesContext = createNewResourcesContext()
@@ -183,6 +382,16 @@ class SafetyCenterResourcesContextTest {
}
@Test
+ fun getIconByDrawableByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getIconByDrawableName("valid_drawable")
+ }
+ }
+
+ @Test
fun getColorByName_validColor_returnsColor() {
val resourcesContext = createNewResourcesContext()
@@ -205,21 +414,22 @@ class SafetyCenterResourcesContextTest {
}
}
+ @Test
+ fun getColorByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesContext =
+ createNewResourcesContext(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesContext.getColorByName("valid_color")
+ }
+ }
+
private fun createNewResourcesContext(
resourcesApkAction: String = RESOURCES_APK_ACTION,
resourcesApkPath: String = "",
- configName: String = CONFIG_NAME,
flags: Int = 0,
fallback: Boolean = false
- ) =
- SafetyCenterResourcesContext(
- context,
- resourcesApkAction,
- resourcesApkPath,
- configName,
- flags,
- fallback
- )
+ ) = SafetyCenterResourcesContext(context, resourcesApkAction, resourcesApkPath, flags, fallback)
companion object {
const val RESOURCES_APK_ACTION =