Loading core/java/com/android/internal/app/ChooserActivity.java +38 −37 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.metrics.LogMaker; Loading Loading @@ -1465,14 +1466,6 @@ public class ChooserActivity extends ResolverActivity { return null; } public Drawable getBadgeIcon() { return null; } public CharSequence getBadgeContentDescription() { return null; } public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return null; } Loading Loading @@ -1561,18 +1554,15 @@ public class ChooserActivity extends ResolverActivity { */ // TODO(121287224): Refactor code to apply the suggestion above private Drawable getChooserTargetIconDrawable(ChooserTarget target) { Drawable directShareIcon = null; // First get the target drawable and associated activity info final Icon icon = target.getIcon(); if (icon != null) { return icon.loadDrawable(ChooserActivity.this); } if (!USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { return null; } directShareIcon = icon.loadDrawable(ChooserActivity.this); } else if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { Bundle extras = target.getIntentExtras(); if (extras == null || !extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { return null; } if (extras != null && extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID); LauncherApps launcherApps = (LauncherApps) getSystemService( Context.LAUNCHER_APPS_SERVICE); Loading @@ -1582,10 +1572,31 @@ public class ChooserActivity extends ResolverActivity { q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC); final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser()); if (shortcuts != null && shortcuts.size() > 0) { return launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); directShareIcon = launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); } } } return null; if (directShareIcon == null) return null; ActivityInfo info = null; try { info = mPm.getActivityInfo(target.getComponentName(), 0); } catch (NameNotFoundException error) { Log.e(TAG, "Could not find activity associated with ChooserTarget"); } if (info == null) return null; // Now fetch app icon and raster with no badging even in work profile Bitmap appIcon = (new ActivityInfoPresentationGetter(info)).getIconBitmap(); // Raster target drawable with appIcon as a badge SimpleIconFactory sif = SimpleIconFactory.obtain(ChooserActivity.this); Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); sif.recycle(); return new BitmapDrawable(getResources(), directShareBadgedIcon); } public float getModifiedScore() { Loading Loading @@ -1683,16 +1694,6 @@ public class ChooserActivity extends ResolverActivity { return mDisplayIcon; } @Override public Drawable getBadgeIcon() { return mBadgeIcon; } @Override public CharSequence getBadgeContentDescription() { return mBadgeContentDescription; } public ChooserTarget getChooserTarget() { return mChooserTarget; } Loading core/java/com/android/internal/app/ResolverActivity.java +125 −95 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; Loading Loading @@ -133,8 +133,6 @@ public class ResolverActivity extends Activity { /** See {@link #setRetainInOnStop}. */ private boolean mRetainInOnStop; SimpleIconFactory mSimpleIconFactory; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { mAdapter.handlePackagesChanged(); Loading Loading @@ -311,11 +309,6 @@ public class ResolverActivity extends Activity { // as to mitigate Intent Capturing vulnerability mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables; final int iconSize = getResources().getDimensionPixelSize(R.dimen.resolver_icon_size); final int badgeSize = getResources().getDimensionPixelSize(R.dimen.resolver_badge_size); mSimpleIconFactory = new SimpleIconFactory(this, mIconDpi, iconSize, badgeSize); mSimpleIconFactory.setWrapperBackgroundColor(Color.WHITE); if (configureContentView(mIntents, initialIntents, rList)) { return; } Loading Loading @@ -500,64 +493,150 @@ public class ResolverActivity extends Activity { } } @Nullable Drawable getIcon(Resources res, int resId) { Drawable result; try { result = res.getDrawableForDensity(resId, mIconDpi); } catch (Resources.NotFoundException e) { result = null; } return result; } /** * Loads the icon for the provided ResolveInfo. Defaults to using the application icon over * Loads the icon for the provided ApplicationInfo. Defaults to using the application icon over * any IntentFilter or Activity icon to increase user understanding, with an exception for * applications that hold the right permission. Always attempts to use icon resources over * PackageManager loading mechanisms so badging can be done by iconloader. */ Drawable loadIconForResolveInfo(ResolveInfo ri) { Drawable dr = null; private abstract class TargetPresentationGetter { @Nullable abstract Drawable getIconSubstitute(); @Nullable abstract String getAppSubLabel(); // Allow for app icon override given the right permission if (PackageManager.PERMISSION_GRANTED == mPm.checkPermission( private final ApplicationInfo mAi; private final boolean mHasSubstitutePermission; TargetPresentationGetter(ApplicationInfo ai) { mAi = ai; mHasSubstitutePermission = PackageManager.PERMISSION_GRANTED == mPm.checkPermission( android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON, ri.activityInfo.applicationInfo.packageName)) { mAi.packageName); } Drawable getIcon() { return new BitmapDrawable(getResources(), getIconBitmap()); } Bitmap getIconBitmap() { Drawable dr = null; if (mHasSubstitutePermission) { dr = getIconSubstitute(); } if (dr == null) { try { if (ri.resolvePackageName != null && ri.icon != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon); if (mAi.icon != 0) { dr = loadIconFromResource(mPm.getResourcesForApplication(mAi), mAi.icon); } } catch (NameNotFoundException ignore) { } } // Fall back to ApplicationInfo#loadIcon if nothing has been loaded if (dr == null) { final int iconRes = ri.getIconResource(); if (iconRes != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes); dr = mAi.loadIcon(mPm); } SimpleIconFactory sif = SimpleIconFactory.obtain(ResolverActivity.this); Bitmap icon = sif.createUserBadgedIconBitmap(dr, Process.myUserHandle()); sif.recycle(); return icon; } String getLabel() { String label = null; // Apps with the substitute permission will always show the sublabel as their label if (mHasSubstitutePermission) { label = getAppSubLabel(); } if (label == null) { label = (String) mAi.loadLabel(mPm); } return label; } String getSubLabel() { // Apps with the substitute permission will never have a sublabel if (mHasSubstitutePermission) return null; return getAppSubLabel(); } @Nullable protected Drawable loadIconFromResource(Resources res, int resId) { return res.getDrawableForDensity(resId, mIconDpi); } } protected class ResolveInfoPresentationGetter extends TargetPresentationGetter { private final ResolveInfo mRi; ResolveInfoPresentationGetter(ResolveInfo ri) { super(ri.activityInfo.applicationInfo); mRi = ri; } @Override Drawable getIconSubstitute() { Drawable dr = null; try { // Do not use ResolveInfo#getIconResource() as it defaults to the app if (mRi.resolvePackageName != null && mRi.icon != 0) { dr = loadIconFromResource( mPm.getResourcesForApplication(mRi.resolvePackageName), mRi.icon); } } catch (NameNotFoundException e) { Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + "couldn't find resources for package", e); } return dr; } // Use app icons for better user association if (dr == null) { @Override String getAppSubLabel() { return (String) mRi.loadLabel(mPm); } } protected class ActivityInfoPresentationGetter extends TargetPresentationGetter { private final ActivityInfo mActivityInfo; protected ActivityInfoPresentationGetter(ActivityInfo activityInfo) { super(activityInfo.applicationInfo); mActivityInfo = activityInfo; } @Override Drawable getIconSubstitute() { Drawable dr = null; try { dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.applicationInfo), ri.activityInfo.applicationInfo.icon); } catch (NameNotFoundException ignore) { // Do not use ActivityInfo#getIconResource() as it defaults to the app if (mActivityInfo.icon != 0) { dr = loadIconFromResource( mPm.getResourcesForApplication(mActivityInfo.applicationInfo), mActivityInfo.icon); } } catch (NameNotFoundException e) { Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + "couldn't find resources for package", e); } // Fall back to ApplicationInfo#loadIcon if nothing has been loaded if (dr == null) { dr = ri.activityInfo.applicationInfo.loadIcon(mPm); return dr; } @Override String getAppSubLabel() { return (String) mActivityInfo.loadLabel(mPm); } } return new BitmapDrawable(this.getResources(), mSimpleIconFactory.createUserBadgedIconBitmap(dr, Process.myUserHandle())); Drawable loadIconForResolveInfo(ResolveInfo ri) { return (new ResolveInfoPresentationGetter(ri)).getIcon(); } @Override Loading Loading @@ -1250,33 +1329,6 @@ public class ResolverActivity extends Activity { return mDisplayIcon; } public Drawable getBadgeIcon() { // We only expose a badge if we have extended info. // The badge is a higher-priority disambiguation signal // but we don't need one if we wouldn't show extended info at all. if (TextUtils.isEmpty(getExtendedInfo())) { return null; } if (mBadge == null && mResolveInfo != null && mResolveInfo.activityInfo != null && mResolveInfo.activityInfo.applicationInfo != null) { if (mResolveInfo.activityInfo.icon == 0 || mResolveInfo.activityInfo.icon == mResolveInfo.activityInfo.applicationInfo.icon) { // Badging an icon with exactly the same icon is silly. // If the activityInfo icon resid is 0 it will fall back // to the application's icon, making it a match. return null; } mBadge = mResolveInfo.activityInfo.applicationInfo.loadIcon(mPm); } return mBadge; } @Override public CharSequence getBadgeContentDescription() { return null; } @Override public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return new DisplayResolveInfo(this, fillInIntent, flags); Loading Loading @@ -1413,20 +1465,10 @@ public class ResolverActivity extends Activity { CharSequence getExtendedInfo(); /** * @return The drawable that should be used to represent this target * @return The drawable that should be used to represent this target including badge */ Drawable getDisplayIcon(); /** * @return The (small) icon to badge the target with */ Drawable getBadgeIcon(); /** * @return The content description for the badge icon */ CharSequence getBadgeContentDescription(); /** * Clone this target with the given fill-in information. */ Loading Loading @@ -1963,16 +2005,6 @@ public class ResolverActivity extends Activity { new LoadAdapterIconTask((DisplayResolveInfo) info).execute(); } holder.icon.setImageDrawable(info.getDisplayIcon()); if (holder.badge != null) { final Drawable badge = info.getBadgeIcon(); if (badge != null) { holder.badge.setImageDrawable(badge); holder.badge.setContentDescription(info.getBadgeContentDescription()); holder.badge.setVisibility(View.VISIBLE); } else { holder.badge.setVisibility(View.GONE); } } } } Loading Loading @@ -2027,13 +2059,11 @@ public class ResolverActivity extends Activity { public TextView text; public TextView text2; public ImageView icon; public ImageView badge; public ViewHolder(View view) { text = (TextView) view.findViewById(com.android.internal.R.id.text1); text2 = (TextView) view.findViewById(com.android.internal.R.id.text2); icon = (ImageView) view.findViewById(R.id.icon); badge = (ImageView) view.findViewById(R.id.target_badge); } } Loading core/java/com/android/internal/app/SimpleIconFactory.java +43 −2 Original line number Diff line number Diff line Loading @@ -16,11 +16,13 @@ package com.android.internal.app; import static android.content.Context.ACTIVITY_SERVICE; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; Loading @@ -42,6 +44,7 @@ import android.graphics.drawable.DrawableWrapper; import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; import android.util.Pools.SynchronizedPool; import com.android.internal.R; Loading @@ -58,6 +61,9 @@ import java.nio.ByteBuffer; @Deprecated public class SimpleIconFactory { private static final SynchronizedPool<SimpleIconFactory> sPool = new SynchronizedPool<>(Runtime.getRuntime().availableProcessors()); private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; private static final float BLUR_FACTOR = 0.5f / 48; Loading @@ -73,11 +79,46 @@ public class SimpleIconFactory { private Drawable mWrapperIcon; private final Rect mOldBounds = new Rect(); /** * Obtain a SimpleIconFactory from a pool objects. * * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public static SimpleIconFactory obtain(Context ctx) { SimpleIconFactory instance = sPool.acquire(); if (instance == null) { final ActivityManager am = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE); final int iconDpi = (am == null) ? 0 : am.getLauncherLargeIconDensity(); final Resources r = ctx.getResources(); final int iconSize = r.getDimensionPixelSize(R.dimen.resolver_icon_size); final int badgeSize = r.getDimensionPixelSize(R.dimen.resolver_badge_size); instance = new SimpleIconFactory(ctx, iconDpi, iconSize, badgeSize); instance.setWrapperBackgroundColor(Color.WHITE); } return instance; } /** * Recycles the SimpleIconFactory so others may use it. * * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public void recycle() { // Return to default background color setWrapperBackgroundColor(Color.WHITE); sPool.release(this); } /** * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, private SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, int badgeBitmapSize) { mContext = context.getApplicationContext(); mPm = mContext.getPackageManager(); Loading Loading @@ -170,7 +211,7 @@ public class SimpleIconFactory { * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { // Flatten the passed in icon float [] scale = new float[1]; Loading core/res/res/layout/resolve_grid_item.xml +7 −16 Original line number Diff line number Diff line Loading @@ -27,22 +27,13 @@ android:focusable="true" android:background="?attr/selectableItemBackgroundBorderless"> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/icon" android:layout_width="48dp" android:layout_height="48dp" android:layout_width="@dimen/resolver_icon_size" android:layout_height="@dimen/resolver_icon_size" android:layout_marginLeft="3dp" android:layout_marginRight="3dp" android:layout_marginBottom="3dp" android:scaleType="fitCenter" /> <ImageView android:id="@+id/target_badge" android:layout_width="16dp" android:layout_height="16dp" android:layout_gravity="end|bottom" android:visibility="gone" android:scaleType="fitCenter" /> </FrameLayout> <!-- Activity name --> <TextView android:id="@android:id/text1" Loading core/res/res/values/symbols.xml +0 −1 Original line number Diff line number Diff line Loading @@ -2779,7 +2779,6 @@ <java-symbol type="layout" name="chooser_row" /> <java-symbol type="layout" name="chooser_row_direct_share" /> <java-symbol type="id" name="target_badge" /> <java-symbol type="bool" name="config_supportDoubleTapWake" /> <java-symbol type="drawable" name="ic_perm_device_info" /> <java-symbol type="string" name="config_radio_access_family" /> Loading Loading
core/java/com/android/internal/app/ChooserActivity.java +38 −37 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.metrics.LogMaker; Loading Loading @@ -1465,14 +1466,6 @@ public class ChooserActivity extends ResolverActivity { return null; } public Drawable getBadgeIcon() { return null; } public CharSequence getBadgeContentDescription() { return null; } public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return null; } Loading Loading @@ -1561,18 +1554,15 @@ public class ChooserActivity extends ResolverActivity { */ // TODO(121287224): Refactor code to apply the suggestion above private Drawable getChooserTargetIconDrawable(ChooserTarget target) { Drawable directShareIcon = null; // First get the target drawable and associated activity info final Icon icon = target.getIcon(); if (icon != null) { return icon.loadDrawable(ChooserActivity.this); } if (!USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { return null; } directShareIcon = icon.loadDrawable(ChooserActivity.this); } else if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { Bundle extras = target.getIntentExtras(); if (extras == null || !extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { return null; } if (extras != null && extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID); LauncherApps launcherApps = (LauncherApps) getSystemService( Context.LAUNCHER_APPS_SERVICE); Loading @@ -1582,10 +1572,31 @@ public class ChooserActivity extends ResolverActivity { q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC); final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser()); if (shortcuts != null && shortcuts.size() > 0) { return launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); directShareIcon = launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); } } } return null; if (directShareIcon == null) return null; ActivityInfo info = null; try { info = mPm.getActivityInfo(target.getComponentName(), 0); } catch (NameNotFoundException error) { Log.e(TAG, "Could not find activity associated with ChooserTarget"); } if (info == null) return null; // Now fetch app icon and raster with no badging even in work profile Bitmap appIcon = (new ActivityInfoPresentationGetter(info)).getIconBitmap(); // Raster target drawable with appIcon as a badge SimpleIconFactory sif = SimpleIconFactory.obtain(ChooserActivity.this); Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); sif.recycle(); return new BitmapDrawable(getResources(), directShareBadgedIcon); } public float getModifiedScore() { Loading Loading @@ -1683,16 +1694,6 @@ public class ChooserActivity extends ResolverActivity { return mDisplayIcon; } @Override public Drawable getBadgeIcon() { return mBadgeIcon; } @Override public CharSequence getBadgeContentDescription() { return mBadgeContentDescription; } public ChooserTarget getChooserTarget() { return mChooserTarget; } Loading
core/java/com/android/internal/app/ResolverActivity.java +125 −95 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; Loading Loading @@ -133,8 +133,6 @@ public class ResolverActivity extends Activity { /** See {@link #setRetainInOnStop}. */ private boolean mRetainInOnStop; SimpleIconFactory mSimpleIconFactory; private final PackageMonitor mPackageMonitor = new PackageMonitor() { @Override public void onSomePackagesChanged() { mAdapter.handlePackagesChanged(); Loading Loading @@ -311,11 +309,6 @@ public class ResolverActivity extends Activity { // as to mitigate Intent Capturing vulnerability mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables; final int iconSize = getResources().getDimensionPixelSize(R.dimen.resolver_icon_size); final int badgeSize = getResources().getDimensionPixelSize(R.dimen.resolver_badge_size); mSimpleIconFactory = new SimpleIconFactory(this, mIconDpi, iconSize, badgeSize); mSimpleIconFactory.setWrapperBackgroundColor(Color.WHITE); if (configureContentView(mIntents, initialIntents, rList)) { return; } Loading Loading @@ -500,64 +493,150 @@ public class ResolverActivity extends Activity { } } @Nullable Drawable getIcon(Resources res, int resId) { Drawable result; try { result = res.getDrawableForDensity(resId, mIconDpi); } catch (Resources.NotFoundException e) { result = null; } return result; } /** * Loads the icon for the provided ResolveInfo. Defaults to using the application icon over * Loads the icon for the provided ApplicationInfo. Defaults to using the application icon over * any IntentFilter or Activity icon to increase user understanding, with an exception for * applications that hold the right permission. Always attempts to use icon resources over * PackageManager loading mechanisms so badging can be done by iconloader. */ Drawable loadIconForResolveInfo(ResolveInfo ri) { Drawable dr = null; private abstract class TargetPresentationGetter { @Nullable abstract Drawable getIconSubstitute(); @Nullable abstract String getAppSubLabel(); // Allow for app icon override given the right permission if (PackageManager.PERMISSION_GRANTED == mPm.checkPermission( private final ApplicationInfo mAi; private final boolean mHasSubstitutePermission; TargetPresentationGetter(ApplicationInfo ai) { mAi = ai; mHasSubstitutePermission = PackageManager.PERMISSION_GRANTED == mPm.checkPermission( android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON, ri.activityInfo.applicationInfo.packageName)) { mAi.packageName); } Drawable getIcon() { return new BitmapDrawable(getResources(), getIconBitmap()); } Bitmap getIconBitmap() { Drawable dr = null; if (mHasSubstitutePermission) { dr = getIconSubstitute(); } if (dr == null) { try { if (ri.resolvePackageName != null && ri.icon != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon); if (mAi.icon != 0) { dr = loadIconFromResource(mPm.getResourcesForApplication(mAi), mAi.icon); } } catch (NameNotFoundException ignore) { } } // Fall back to ApplicationInfo#loadIcon if nothing has been loaded if (dr == null) { final int iconRes = ri.getIconResource(); if (iconRes != 0) { dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes); dr = mAi.loadIcon(mPm); } SimpleIconFactory sif = SimpleIconFactory.obtain(ResolverActivity.this); Bitmap icon = sif.createUserBadgedIconBitmap(dr, Process.myUserHandle()); sif.recycle(); return icon; } String getLabel() { String label = null; // Apps with the substitute permission will always show the sublabel as their label if (mHasSubstitutePermission) { label = getAppSubLabel(); } if (label == null) { label = (String) mAi.loadLabel(mPm); } return label; } String getSubLabel() { // Apps with the substitute permission will never have a sublabel if (mHasSubstitutePermission) return null; return getAppSubLabel(); } @Nullable protected Drawable loadIconFromResource(Resources res, int resId) { return res.getDrawableForDensity(resId, mIconDpi); } } protected class ResolveInfoPresentationGetter extends TargetPresentationGetter { private final ResolveInfo mRi; ResolveInfoPresentationGetter(ResolveInfo ri) { super(ri.activityInfo.applicationInfo); mRi = ri; } @Override Drawable getIconSubstitute() { Drawable dr = null; try { // Do not use ResolveInfo#getIconResource() as it defaults to the app if (mRi.resolvePackageName != null && mRi.icon != 0) { dr = loadIconFromResource( mPm.getResourcesForApplication(mRi.resolvePackageName), mRi.icon); } } catch (NameNotFoundException e) { Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + "couldn't find resources for package", e); } return dr; } // Use app icons for better user association if (dr == null) { @Override String getAppSubLabel() { return (String) mRi.loadLabel(mPm); } } protected class ActivityInfoPresentationGetter extends TargetPresentationGetter { private final ActivityInfo mActivityInfo; protected ActivityInfoPresentationGetter(ActivityInfo activityInfo) { super(activityInfo.applicationInfo); mActivityInfo = activityInfo; } @Override Drawable getIconSubstitute() { Drawable dr = null; try { dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.applicationInfo), ri.activityInfo.applicationInfo.icon); } catch (NameNotFoundException ignore) { // Do not use ActivityInfo#getIconResource() as it defaults to the app if (mActivityInfo.icon != 0) { dr = loadIconFromResource( mPm.getResourcesForApplication(mActivityInfo.applicationInfo), mActivityInfo.icon); } } catch (NameNotFoundException e) { Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but " + "couldn't find resources for package", e); } // Fall back to ApplicationInfo#loadIcon if nothing has been loaded if (dr == null) { dr = ri.activityInfo.applicationInfo.loadIcon(mPm); return dr; } @Override String getAppSubLabel() { return (String) mActivityInfo.loadLabel(mPm); } } return new BitmapDrawable(this.getResources(), mSimpleIconFactory.createUserBadgedIconBitmap(dr, Process.myUserHandle())); Drawable loadIconForResolveInfo(ResolveInfo ri) { return (new ResolveInfoPresentationGetter(ri)).getIcon(); } @Override Loading Loading @@ -1250,33 +1329,6 @@ public class ResolverActivity extends Activity { return mDisplayIcon; } public Drawable getBadgeIcon() { // We only expose a badge if we have extended info. // The badge is a higher-priority disambiguation signal // but we don't need one if we wouldn't show extended info at all. if (TextUtils.isEmpty(getExtendedInfo())) { return null; } if (mBadge == null && mResolveInfo != null && mResolveInfo.activityInfo != null && mResolveInfo.activityInfo.applicationInfo != null) { if (mResolveInfo.activityInfo.icon == 0 || mResolveInfo.activityInfo.icon == mResolveInfo.activityInfo.applicationInfo.icon) { // Badging an icon with exactly the same icon is silly. // If the activityInfo icon resid is 0 it will fall back // to the application's icon, making it a match. return null; } mBadge = mResolveInfo.activityInfo.applicationInfo.loadIcon(mPm); } return mBadge; } @Override public CharSequence getBadgeContentDescription() { return null; } @Override public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { return new DisplayResolveInfo(this, fillInIntent, flags); Loading Loading @@ -1413,20 +1465,10 @@ public class ResolverActivity extends Activity { CharSequence getExtendedInfo(); /** * @return The drawable that should be used to represent this target * @return The drawable that should be used to represent this target including badge */ Drawable getDisplayIcon(); /** * @return The (small) icon to badge the target with */ Drawable getBadgeIcon(); /** * @return The content description for the badge icon */ CharSequence getBadgeContentDescription(); /** * Clone this target with the given fill-in information. */ Loading Loading @@ -1963,16 +2005,6 @@ public class ResolverActivity extends Activity { new LoadAdapterIconTask((DisplayResolveInfo) info).execute(); } holder.icon.setImageDrawable(info.getDisplayIcon()); if (holder.badge != null) { final Drawable badge = info.getBadgeIcon(); if (badge != null) { holder.badge.setImageDrawable(badge); holder.badge.setContentDescription(info.getBadgeContentDescription()); holder.badge.setVisibility(View.VISIBLE); } else { holder.badge.setVisibility(View.GONE); } } } } Loading Loading @@ -2027,13 +2059,11 @@ public class ResolverActivity extends Activity { public TextView text; public TextView text2; public ImageView icon; public ImageView badge; public ViewHolder(View view) { text = (TextView) view.findViewById(com.android.internal.R.id.text1); text2 = (TextView) view.findViewById(com.android.internal.R.id.text2); icon = (ImageView) view.findViewById(R.id.icon); badge = (ImageView) view.findViewById(R.id.target_badge); } } Loading
core/java/com/android/internal/app/SimpleIconFactory.java +43 −2 Original line number Diff line number Diff line Loading @@ -16,11 +16,13 @@ package com.android.internal.app; import static android.content.Context.ACTIVITY_SERVICE; import static android.graphics.Paint.DITHER_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; Loading @@ -42,6 +44,7 @@ import android.graphics.drawable.DrawableWrapper; import android.os.Process; import android.os.UserHandle; import android.util.AttributeSet; import android.util.Pools.SynchronizedPool; import com.android.internal.R; Loading @@ -58,6 +61,9 @@ import java.nio.ByteBuffer; @Deprecated public class SimpleIconFactory { private static final SynchronizedPool<SimpleIconFactory> sPool = new SynchronizedPool<>(Runtime.getRuntime().availableProcessors()); private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE; private static final float BLUR_FACTOR = 0.5f / 48; Loading @@ -73,11 +79,46 @@ public class SimpleIconFactory { private Drawable mWrapperIcon; private final Rect mOldBounds = new Rect(); /** * Obtain a SimpleIconFactory from a pool objects. * * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public static SimpleIconFactory obtain(Context ctx) { SimpleIconFactory instance = sPool.acquire(); if (instance == null) { final ActivityManager am = (ActivityManager) ctx.getSystemService(ACTIVITY_SERVICE); final int iconDpi = (am == null) ? 0 : am.getLauncherLargeIconDensity(); final Resources r = ctx.getResources(); final int iconSize = r.getDimensionPixelSize(R.dimen.resolver_icon_size); final int badgeSize = r.getDimensionPixelSize(R.dimen.resolver_badge_size); instance = new SimpleIconFactory(ctx, iconDpi, iconSize, badgeSize); instance.setWrapperBackgroundColor(Color.WHITE); } return instance; } /** * Recycles the SimpleIconFactory so others may use it. * * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public void recycle() { // Return to default background color setWrapperBackgroundColor(Color.WHITE); sPool.release(this); } /** * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, private SimpleIconFactory(Context context, int fillResIconDpi, int iconBitmapSize, int badgeBitmapSize) { mContext = context.getApplicationContext(); mPm = mContext.getPackageManager(); Loading Loading @@ -170,7 +211,7 @@ public class SimpleIconFactory { * @deprecated Do not use, functionality will be replaced by iconloader lib eventually. */ @Deprecated public Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { Bitmap createAppBadgedIconBitmap(@Nullable Drawable icon, Bitmap renderedAppIcon) { // Flatten the passed in icon float [] scale = new float[1]; Loading
core/res/res/layout/resolve_grid_item.xml +7 −16 Original line number Diff line number Diff line Loading @@ -27,22 +27,13 @@ android:focusable="true" android:background="?attr/selectableItemBackgroundBorderless"> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/icon" android:layout_width="48dp" android:layout_height="48dp" android:layout_width="@dimen/resolver_icon_size" android:layout_height="@dimen/resolver_icon_size" android:layout_marginLeft="3dp" android:layout_marginRight="3dp" android:layout_marginBottom="3dp" android:scaleType="fitCenter" /> <ImageView android:id="@+id/target_badge" android:layout_width="16dp" android:layout_height="16dp" android:layout_gravity="end|bottom" android:visibility="gone" android:scaleType="fitCenter" /> </FrameLayout> <!-- Activity name --> <TextView android:id="@android:id/text1" Loading
core/res/res/values/symbols.xml +0 −1 Original line number Diff line number Diff line Loading @@ -2779,7 +2779,6 @@ <java-symbol type="layout" name="chooser_row" /> <java-symbol type="layout" name="chooser_row_direct_share" /> <java-symbol type="id" name="target_badge" /> <java-symbol type="bool" name="config_supportDoubleTapWake" /> <java-symbol type="drawable" name="ic_perm_device_info" /> <java-symbol type="string" name="config_radio_access_family" /> Loading