summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/widget/LocalImageResolver.java65
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java47
2 files changed, 108 insertions, 4 deletions
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index b11ea2961c17..9ef7ce38fc09 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -19,6 +19,8 @@ package com.android.internal.widget;
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
@@ -109,13 +111,13 @@ public class LocalImageResolver {
}
break;
case Icon.TYPE_RESOURCE:
- if (!(TextUtils.isEmpty(icon.getResPackage())
- || context.getPackageName().equals(icon.getResPackage()))) {
- // We can't properly resolve icons from other packages here, so fall back.
+ Resources res = resolveResourcesForIcon(context, icon);
+ if (res == null) {
+ // We couldn't resolve resources properly, fall back to icon loading.
return icon.loadDrawable(context);
}
- Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight);
+ Drawable result = resolveImage(res, icon.getResId(), maxWidth, maxHeight);
if (result != null) {
return tintDrawable(icon, result);
}
@@ -159,6 +161,13 @@ public class LocalImageResolver {
}
@Nullable
+ private static Drawable resolveImage(Resources res, @DrawableRes int resId, int maxWidth,
+ int maxHeight) {
+ final ImageDecoder.Source source = ImageDecoder.createSource(res, resId);
+ return resolveImage(source, maxWidth, maxHeight);
+ }
+
+ @Nullable
private static Drawable resolveBitmapImage(Icon icon, Context context, int maxWidth,
int maxHeight) {
@@ -259,4 +268,52 @@ public class LocalImageResolver {
}
return icon.getUri();
}
+
+ /**
+ * Resolves the correct resources package for a given Icon - it may come from another
+ * package.
+ *
+ * @see Icon#loadDrawableInner(Context)
+ * @hide
+ *
+ * @return resources instance if the operation succeeded, null otherwise
+ */
+ @Nullable
+ @VisibleForTesting
+ public static Resources resolveResourcesForIcon(Context context, Icon icon) {
+ if (icon.getType() != Icon.TYPE_RESOURCE) {
+ return null;
+ }
+
+ // Icons cache resolved resources, use cache if available.
+ Resources res = icon.getResources();
+ if (res != null) {
+ return res;
+ }
+
+ String resPackage = icon.getResPackage();
+ // No package means we try to use current context.
+ if (TextUtils.isEmpty(resPackage) || context.getPackageName().equals(resPackage)) {
+ return context.getResources();
+ }
+
+ if ("android".equals(resPackage)) {
+ return Resources.getSystem();
+ }
+
+ final PackageManager pm = context.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(resPackage,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.GET_SHARED_LIBRARY_FILES);
+ if (ai != null) {
+ return pm.getResourcesForApplication(ai);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, String.format("Unable to resolve package %s for icon %s", resPackage, icon));
+ return null;
+ }
+
+ return null;
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
index 0cee526651a6..271a20b71106 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
@@ -17,6 +17,8 @@
package com.android.internal.widget;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
@@ -279,4 +281,49 @@ public class LocalImageResolverTest {
// This drawable must not be loaded - if it was, the code ignored the package specification.
assertThat(d).isNull();
}
+
+ @Test
+ public void resolveResourcesForIcon_notAResourceIcon_returnsNull() {
+ Icon icon = Icon.createWithContentUri(Uri.parse("some_uri"));
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_localPackageIcon_returnsPackageResources() {
+ Icon icon = Icon.createWithResource(mContext, R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_iconWithoutPackageSpecificed_returnsPackageResources() {
+ Icon icon = Icon.createWithResource("", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_systemPackageSpecified_returnsSystemPackage() {
+ Icon icon = Icon.createWithResource("android", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isSameInstanceAs(
+ Resources.getSystem());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_differentPackageSpecified_returnsPackageResources() throws
+ PackageManager.NameNotFoundException {
+ String pkg = "com.android.settings";
+ Resources res = mContext.getPackageManager().getResourcesForApplication(pkg);
+ int resId = res.getIdentifier("ic_android", "drawable", pkg);
+ Icon icon = Icon.createWithResource(pkg, resId);
+
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon).getDrawable(resId,
+ mContext.getTheme())).isNotNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_invalidPackageSpecified_returnsNull() {
+ Icon icon = Icon.createWithResource("invalid.package", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
}