Skip to content

Commit

Permalink
Check for null results from PackageManager.getApplicationInfo
Browse files Browse the repository at this point in the history
This should never happen based on the API documention. However,
Compose's preview API seems to return null anyway. Catch for the
exception for now while we wait for a fix in the tooling.
  • Loading branch information
sjudd committed Feb 13, 2023
1 parent c283043 commit 0f9aea2
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import androidx.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -24,18 +26,24 @@ public ManifestParser(Context context) {
this.context = context;
}

// getApplicationInfo returns null in Compose previews, see #4977 and b/263613353.
@SuppressWarnings("ConstantConditions")
@Nullable
private ApplicationInfo getOurApplicationInfo() throws NameNotFoundException {
return context
.getPackageManager()
.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
}

@SuppressWarnings("deprecation")
public List<GlideModule> parse() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Loading Glide modules");
}
List<GlideModule> modules = new ArrayList<>();
try {
ApplicationInfo appInfo =
context
.getPackageManager()
.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
if (appInfo.metaData == null) {
ApplicationInfo appInfo = getOurApplicationInfo();
if (appInfo == null || appInfo.metaData == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Got null app info metadata");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.bumptech.glide.module;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
Expand All @@ -16,6 +21,7 @@
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
Expand All @@ -27,6 +33,7 @@
@SuppressWarnings("deprecation")
public class ManifestParserTest {
private static final String MODULE_VALUE = "GlideModule";
private static final String PACKAGE_NAME = "com.bumptech.test";

@Mock private Context context;
private ManifestParser parser;
Expand All @@ -38,17 +45,27 @@ public void setUp() throws PackageManager.NameNotFoundException {
applicationInfo = new ApplicationInfo();
applicationInfo.metaData = new Bundle();

String packageName = "com.bumptech.test";
when(context.getPackageName()).thenReturn(packageName);
when(context.getPackageName()).thenReturn(PACKAGE_NAME);

PackageManager pm = mock(PackageManager.class);
when(pm.getApplicationInfo(eq(packageName), eq(PackageManager.GET_META_DATA)))
when(pm.getApplicationInfo(eq(PACKAGE_NAME), eq(PackageManager.GET_META_DATA)))
.thenReturn(applicationInfo);
when(context.getPackageManager()).thenReturn(pm);

parser = new ManifestParser(context);
}

// TODO(#4977): Remove this after the bug in Compose's previews is fixed.
@Test
public void parse_withNullApplicationInfo_doesNotThrow() throws NameNotFoundException {
PackageManager pm = mock(PackageManager.class);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(null);
when(context.getPackageManager()).thenReturn(pm);

parser = new ManifestParser(context);
parser.parse();
}

@Test
public void testParse_returnsEmptyListIfNoModulesListed() {
assertThat(parser.parse()).isEmpty();
Expand Down Expand Up @@ -78,7 +95,6 @@ public void testParse_withMultipleValidModuleNames_returnsListContainingModules(
@Test
public void testParse_withValidModuleName_ignoresMetadataWithoutGlideModuleValue() {
applicationInfo.metaData.putString(TestModule1.class.getName(), MODULE_VALUE + "test");

assertThat(parser.parse()).isEmpty();
}

Expand All @@ -96,13 +112,35 @@ public void testThrows_whenClassInManifestIsNotAModule() {
parser.parse();
}

@Test(expected = RuntimeException.class)
public void testThrows_whenPackageNameNotFound() {
when(context.getPackageName()).thenReturn("fakePackageName");
@Test
public void parse_withNullMetadata_doesNotThrow() throws NameNotFoundException {
PackageManager pm = mock(PackageManager.class);
ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.metaData = null;
when(pm.getApplicationInfo(eq(PACKAGE_NAME), eq(PackageManager.GET_META_DATA)))
.thenReturn(applicationInfo);
when(context.getPackageManager()).thenReturn(pm);

parser.parse();
}

@Test
public void parse_withMissingName_throwsRuntimeException() throws NameNotFoundException {
PackageManager pm = mock(PackageManager.class);
doThrow(new NameNotFoundException("name")).when(pm).getApplicationInfo(anyString(), anyInt());
when(context.getPackageManager()).thenReturn(pm);

assertThrows(
"Unable to find metadata to parse GlideModules",
RuntimeException.class,
new ThrowingRunnable() {
@Override
public void run() {
parser.parse();
}
});
}

private void addModuleToManifest(Class<?> moduleClass) {
addToManifest(moduleClass.getName());
}
Expand Down

0 comments on commit 0f9aea2

Please sign in to comment.