Merge "Prevent loading of Icon resources from the wrong package" into tm-qpr-dev
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -158,6 +160,13 @@ public class LocalImageResolver {
|
||||
return resolveImage(source, maxWidth, maxHeight);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user