diff options
| author | 2022-10-06 18:40:29 -0700 | |
|---|---|---|
| committer | 2022-11-04 16:00:15 -0700 | |
| commit | 0c7df5fef314e451cac57521b10e5f34cc269d92 (patch) | |
| tree | cd6fb7fadc3a10b6589a293634ee3d840c533d96 /java/src/com | |
| parent | d98c446b684a41d073a28093d139b94642f45ac9 (diff) | |
Simplify SelectableTargetInfo dependencies
Remove “functional” (Context, PackageManager, and
SelectableTargetInfoCommunicator) and obsolete dependencies from
SelectableTargetInfo.
Changes to SelectableTargetInfo:
1. Fields mBadgeIcon, mBadgeContentDescriptor were never read and thus
removed.
2. Values previously provided by SelectableTargetInfoCommunicator are
inlined or pre-calculated:
- getTargetIntent() used in the resolved intent calculation replaced
with a pre-calculated resolved intent value (we can do it as target
intent does not change);
- getReferrerFillInIntent() passed as an argument (we can do it as the
value does not change).
3. As ChooserListAdapter.LoadDirectShareIconTask was the only place that
invoked SelectableTargetInfo#loadIcon(), icon loading logic,
SelectableTargetInfo#getChooserTargetIconDrawable method, is moved
over there and the related code is deleted from SelectableTargetInfo.
4. SelectableTargetInfo.SelectableTargetInfoCommunicator
#makePresentatinGetter() removed as not used.
Changes to TargetInfo (and related classes):
1. TargetInfo#setDrawableIcon() is added to the interface as a way for
ChooserListAdapter#LoadDirectShareIconTask to update the icon.
2. NotSelectableTargetInfo#newPlaceHolderInfo() changed to receive a
context that would be used by the target it creates.
3. After the aforementioned changes no implementation of the
TargetInfo#getDisplayIcon actually uses its Context argument, thus it
is deleted.
4. A default implementation added for TargetInfo#hasDisplayIcon method
as all implementations, essentially, were the same.
5. TargetInfo#loadIcon removed as not used.
Fix: 257285229
Test: manual functinality test
Test: atest IntentResolverUnitTests
Change-Id: I448ebed9c5346092ebca6c4e356830c55288d55b
Diffstat (limited to 'java/src/com')
8 files changed, 172 insertions, 225 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index 3ccefe1b..938fbb0d 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -115,7 +115,6 @@ import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; -import com.android.intentresolver.ResolverListAdapter.ActivityInfoPresentationGetter; import com.android.intentresolver.ResolverListAdapter.ViewHolder; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.MultiDisplayResolveInfo; @@ -1128,7 +1127,7 @@ public class ChooserActivity extends ResolverActivity implements if (ti == null) return null; final Button b = createActionButton( - ti.getDisplayIcon(this), + ti.getDisplayIcon(), ti.getDisplayLabel(), (View unused) -> { // Log share completion via nearby @@ -1151,7 +1150,7 @@ public class ChooserActivity extends ResolverActivity implements if (ti == null) return null; final Button b = createActionButton( - ti.getDisplayIcon(this), + ti.getDisplayIcon(), ti.getDisplayLabel(), (View unused) -> { // Log share completion via edit @@ -2458,11 +2457,6 @@ public class ChooserActivity extends ResolverActivity implements } @Override // SelectableTargetInfoCommunicator - public ActivityInfoPresentationGetter makePresentationGetter(ActivityInfo info) { - return mChooserMultiProfilePagerAdapter.getActiveListAdapter().makePresentationGetter(info); - } - - @Override // SelectableTargetInfoCommunicator public Intent getReferrerFillInIntent() { return mReferrerFillInIntent; } diff --git a/java/src/com/android/intentresolver/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java index 92cd0043..f20ee38f 100644 --- a/java/src/com/android/intentresolver/ChooserListAdapter.java +++ b/java/src/com/android/intentresolver/ChooserListAdapter.java @@ -27,10 +27,14 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.LabeledIntent; +import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.os.Trace; import android.os.UserManager; @@ -42,10 +46,13 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.WorkerThread; + import com.android.intentresolver.ResolverActivity.ResolvedComponentInfo; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.MultiDisplayResolveInfo; import com.android.intentresolver.chooser.NotSelectableTargetInfo; +import com.android.intentresolver.chooser.SelectableTargetInfo; import com.android.intentresolver.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator; import com.android.intentresolver.chooser.TargetInfo; import com.android.internal.annotations.VisibleForTesting; @@ -84,8 +91,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private final Map<TargetInfo, AsyncTask> mIconLoaders = new HashMap<>(); // Reserve spots for incoming direct share targets by adding placeholders - private TargetInfo mPlaceHolderTargetInfo = - NotSelectableTargetInfo.newPlaceHolderTargetInfo(); + private final TargetInfo mPlaceHolderTargetInfo; private final List<TargetInfo> mServiceTargets = new ArrayList<>(); private final List<DisplayResolveInfo> mCallerTargets = new ArrayList<>(); @@ -142,6 +148,7 @@ public class ChooserListAdapter extends ResolverListAdapter { resolverListController, chooserListCommunicator, false); mChooserListCommunicator = chooserListCommunicator; + mPlaceHolderTargetInfo = NotSelectableTargetInfo.newPlaceHolderTargetInfo(context); createPlaceHolders(); mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator; mChooserActivityLogger = chooserActivityLogger; @@ -256,7 +263,7 @@ public class ChooserListAdapter extends ResolverListAdapter { extendedInfo != null ? extendedInfo : "", appName); holder.updateContentDescription(contentDescription); if (!info.hasDisplayIcon()) { - loadDirectShareIcon(info); + loadDirectShareIcon((SelectableTargetInfo) info); } } else if (info.isDisplayResolveInfo()) { DisplayResolveInfo dri = (DisplayResolveInfo) info; @@ -302,7 +309,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } } - private void loadDirectShareIcon(TargetInfo info) { + private void loadDirectShareIcon(SelectableTargetInfo info) { LoadDirectShareIconTask task = (LoadDirectShareIconTask) mIconLoaders.get(info); if (task == null) { task = createLoadDirectShareIconTask(info); @@ -312,8 +319,10 @@ public class ChooserListAdapter extends ResolverListAdapter { } @VisibleForTesting - protected LoadDirectShareIconTask createLoadDirectShareIconTask(TargetInfo info) { - return new LoadDirectShareIconTask(info); + protected LoadDirectShareIconTask createLoadDirectShareIconTask(SelectableTargetInfo info) { + return new LoadDirectShareIconTask( + mContext.createContextAsUser(getUserHandle(), 0), + info); } void updateAlphabeticalList() { @@ -545,7 +554,8 @@ public class ChooserListAdapter extends ResolverListAdapter { directShareToShortcutInfos, directShareToAppTargets, mContext.createContextAsUser(getUserHandle(), 0), - mSelectableTargetInfoCommunicator, + mSelectableTargetInfoCommunicator.getTargetIntent(), + mSelectableTargetInfoCommunicator.getReferrerFillInIntent(), mChooserListCommunicator.getMaxRankedTargets(), mServiceTargets); if (isUpdated) { @@ -641,25 +651,76 @@ public class ChooserListAdapter extends ResolverListAdapter { * Loads direct share targets icons. */ @VisibleForTesting - public class LoadDirectShareIconTask extends AsyncTask<Void, Void, Boolean> { - private final TargetInfo mTargetInfo; + public class LoadDirectShareIconTask extends AsyncTask<Void, Void, Drawable> { + private final Context mContext; + private final SelectableTargetInfo mTargetInfo; - private LoadDirectShareIconTask(TargetInfo targetInfo) { + private LoadDirectShareIconTask(Context context, SelectableTargetInfo targetInfo) { + mContext = context; mTargetInfo = targetInfo; } @Override - protected Boolean doInBackground(Void... voids) { - return mTargetInfo.loadIcon(); + protected Drawable doInBackground(Void... voids) { + return getChooserTargetIconDrawable( + mContext, + mTargetInfo.getChooserTargetIcon(), + mTargetInfo.getChooserTargetComponentName(), + mTargetInfo.getDirectShareShortcutInfo()); } @Override - protected void onPostExecute(Boolean isLoaded) { - if (isLoaded) { + protected void onPostExecute(@Nullable Drawable icon) { + if (icon != null && !mTargetInfo.hasDisplayIcon()) { + mTargetInfo.setDisplayIcon(icon); notifyDataSetChanged(); } } + @WorkerThread + private Drawable getChooserTargetIconDrawable( + Context context, + @Nullable Icon icon, + ComponentName targetComponentName, + @Nullable ShortcutInfo shortcutInfo) { + Drawable directShareIcon = null; + + // First get the target drawable and associated activity info + if (icon != null) { + directShareIcon = icon.loadDrawable(context); + } else if (shortcutInfo != null) { + LauncherApps launcherApps = context.getSystemService(LauncherApps.class); + if (launcherApps != null) { + directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0); + } + } + + if (directShareIcon == null) { + return null; + } + + ActivityInfo info = null; + try { + info = context.getPackageManager().getActivityInfo(targetComponentName, 0); + } catch (PackageManager.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 = makePresentationGetter(info).getIconBitmap(null); + + // Raster target drawable with appIcon as a badge + SimpleIconFactory sif = SimpleIconFactory.obtain(context); + Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); + sif.recycle(); + + return new BitmapDrawable(context.getResources(), directShareBadgedIcon); + } + /** * An alias for execute to use with unit tests. */ diff --git a/java/src/com/android/intentresolver/ResolverListAdapter.java b/java/src/com/android/intentresolver/ResolverListAdapter.java index 63da842d..f74c33c0 100644 --- a/java/src/com/android/intentresolver/ResolverListAdapter.java +++ b/java/src/com/android/intentresolver/ResolverListAdapter.java @@ -921,7 +921,7 @@ public class ResolverListAdapter extends BaseAdapter { } public void bindIcon(TargetInfo info) { - icon.setImageDrawable(info.getDisplayIcon(itemView.getContext())); + icon.setImageDrawable(info.getDisplayIcon()); if (info.isSuspended()) { icon.setColorFilter(getSuspendedColorMatrix()); } else { diff --git a/java/src/com/android/intentresolver/ShortcutSelectionLogic.java b/java/src/com/android/intentresolver/ShortcutSelectionLogic.java index 39187bdb..645b9391 100644 --- a/java/src/com/android/intentresolver/ShortcutSelectionLogic.java +++ b/java/src/com/android/intentresolver/ShortcutSelectionLogic.java @@ -19,13 +19,15 @@ package com.android.intentresolver; import android.annotation.Nullable; import android.app.prediction.AppTarget; import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.service.chooser.ChooserTarget; import android.util.Log; import com.android.intentresolver.chooser.DisplayResolveInfo; import com.android.intentresolver.chooser.SelectableTargetInfo; -import com.android.intentresolver.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator; import com.android.intentresolver.chooser.TargetInfo; import java.util.Collections; @@ -65,7 +67,8 @@ class ShortcutSelectionLogic { Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos, Map<ChooserTarget, AppTarget> directShareToAppTargets, Context userContext, - SelectableTargetInfoCommunicator mSelectableTargetInfoCommunicator, + Intent targetIntent, + Intent referrerFillInIntent, int maxRankedTargets, List<TargetInfo> serviceTargets) { if (DEBUG) { @@ -100,15 +103,28 @@ class ShortcutSelectionLogic { if ((shortcutInfo != null) && shortcutInfo.isPinned()) { targetScore += PINNED_SHORTCUT_TARGET_SCORE_BOOST; } + ResolveInfo backupResolveInfo; + Intent resolvedIntent; + if (origTarget == null) { + resolvedIntent = createResolvedIntentForCallerTarget(target, targetIntent); + backupResolveInfo = userContext.getPackageManager() + .resolveActivity( + resolvedIntent, + PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA)); + } else { + resolvedIntent = origTarget.getResolvedIntent(); + backupResolveInfo = null; + } boolean isInserted = insertServiceTarget( SelectableTargetInfo.newSelectableTargetInfo( - userContext, origTarget, + backupResolveInfo, + resolvedIntent, target, targetScore, - mSelectableTargetInfoCommunicator, shortcutInfo, - directShareToAppTargets.get(target)), + directShareToAppTargets.get(target), + referrerFillInIntent), maxRankedTargets, serviceTargets); @@ -128,6 +144,19 @@ class ShortcutSelectionLogic { return shouldNotify; } + /** + * Creates a resolved intent for a caller-specified target. + * @param target, a caller-specified target. + * @param targetIntent, a target intent for the Chooser (see {@link Intent#EXTRA_INTENT}). + */ + private static Intent createResolvedIntentForCallerTarget( + ChooserTarget target, Intent targetIntent) { + final Intent resolvedIntent = new Intent(targetIntent); + resolvedIntent.setComponent(target.getComponentName()); + resolvedIntent.putExtras(target.getIntentExtras()); + return resolvedIntent; + } + private boolean insertServiceTarget( TargetInfo chooserTargetInfo, int maxRankedTargets, diff --git a/java/src/com/android/intentresolver/chooser/DisplayResolveInfo.java b/java/src/com/android/intentresolver/chooser/DisplayResolveInfo.java index daa69152..16dd28bc 100644 --- a/java/src/com/android/intentresolver/chooser/DisplayResolveInfo.java +++ b/java/src/com/android/intentresolver/chooser/DisplayResolveInfo.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Activity; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -47,7 +46,7 @@ public class DisplayResolveInfo implements TargetInfo { private CharSequence mExtendedInfo; private final Intent mResolvedIntent; private final List<Intent> mSourceIntents = new ArrayList<>(); - private boolean mIsSuspended; + private final boolean mIsSuspended; private ResolveInfoPresentationGetter mResolveInfoPresentationGetter; private boolean mPinned = false; @@ -107,10 +106,14 @@ public class DisplayResolveInfo implements TargetInfo { } - private DisplayResolveInfo(DisplayResolveInfo other, Intent fillInIntent, int flags, + private DisplayResolveInfo( + DisplayResolveInfo other, + Intent fillInIntent, + int flags, ResolveInfoPresentationGetter resolveInfoPresentationGetter) { mSourceIntents.addAll(other.getAllSourceIntents()); mResolveInfo = other.mResolveInfo; + mIsSuspended = other.mIsSuspended; mDisplayLabel = other.mDisplayLabel; mDisplayIcon = other.mDisplayIcon; mExtendedInfo = other.mExtendedInfo; @@ -122,6 +125,7 @@ public class DisplayResolveInfo implements TargetInfo { protected DisplayResolveInfo(DisplayResolveInfo other) { mSourceIntents.addAll(other.getAllSourceIntents()); mResolveInfo = other.mResolveInfo; + mIsSuspended = other.mIsSuspended; mDisplayLabel = other.mDisplayLabel; mDisplayIcon = other.mDisplayIcon; mExtendedInfo = other.mExtendedInfo; @@ -158,7 +162,8 @@ public class DisplayResolveInfo implements TargetInfo { mExtendedInfo = extendedInfo; } - public Drawable getDisplayIcon(Context context) { + @Override + public Drawable getDisplayIcon() { return mDisplayIcon; } @@ -185,10 +190,6 @@ public class DisplayResolveInfo implements TargetInfo { mDisplayIcon = icon; } - public boolean hasDisplayIcon() { - return mDisplayIcon != null; - } - public CharSequence getExtendedInfo() { return mExtendedInfo; } diff --git a/java/src/com/android/intentresolver/chooser/NotSelectableTargetInfo.java b/java/src/com/android/intentresolver/chooser/NotSelectableTargetInfo.java index 8ec52c8a..3b4b89b1 100644 --- a/java/src/com/android/intentresolver/chooser/NotSelectableTargetInfo.java +++ b/java/src/com/android/intentresolver/chooser/NotSelectableTargetInfo.java @@ -45,14 +45,9 @@ public abstract class NotSelectableTargetInfo extends ChooserTargetInfo { } @Override - public Drawable getDisplayIcon(Context context) { + public Drawable getDisplayIcon() { return null; } - - @Override - public boolean hasDisplayIcon() { - return false; - } }; } @@ -60,7 +55,7 @@ public abstract class NotSelectableTargetInfo extends ChooserTargetInfo { * Create a non-selectable {@link TargetInfo} with placeholder content to be displayed * unless/until it can be replaced by the result of a pending asynchronous load. */ - public static TargetInfo newPlaceHolderTargetInfo() { + public static TargetInfo newPlaceHolderTargetInfo(Context context) { return new NotSelectableTargetInfo() { @Override public boolean isPlaceHolderTargetInfo() { @@ -68,7 +63,7 @@ public abstract class NotSelectableTargetInfo extends ChooserTargetInfo { } @Override - public Drawable getDisplayIcon(Context context) { + public Drawable getDisplayIcon() { AnimatedVectorDrawable avd = (AnimatedVectorDrawable) context.getDrawable(R.drawable.chooser_direct_share_icon_placeholder); avd.start(); // Start animation after generation. diff --git a/java/src/com/android/intentresolver/chooser/SelectableTargetInfo.java b/java/src/com/android/intentresolver/chooser/SelectableTargetInfo.java index 7e6e49fb..093020b8 100644 --- a/java/src/com/android/intentresolver/chooser/SelectableTargetInfo.java +++ b/java/src/com/android/intentresolver/chooser/SelectableTargetInfo.java @@ -22,14 +22,8 @@ import android.app.prediction.AppTarget; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.LauncherApps; -import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.Bundle; @@ -42,9 +36,6 @@ import android.util.Log; import com.android.intentresolver.ChooserActivity; import com.android.intentresolver.ResolverActivity; -import com.android.intentresolver.ResolverListAdapter.ActivityInfoPresentationGetter; -import com.android.intentresolver.SimpleIconFactory; -import com.android.internal.annotations.GuardedBy; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import java.util.ArrayList; @@ -65,84 +56,74 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS, DEFAULT_SALT_EXPIRATION_DAYS); - private final Context mContext; @Nullable private final DisplayResolveInfo mSourceInfo; + @Nullable private final ResolveInfo mBackupResolveInfo; + private final Intent mResolvedIntent; private final ChooserTarget mChooserTarget; private final String mDisplayLabel; - private final PackageManager mPm; - private final SelectableTargetInfoCommunicator mSelectableTargetInfoCommunicator; @Nullable private final AppTarget mAppTarget; @Nullable private final ShortcutInfo mShortcutInfo; + + /** + * A refinement intent from the caller, if any (see + * {@link Intent#EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER}) + */ private final Intent mFillInIntent; + + /** + * An intent containing referrer URI (see {@link Activity#getReferrer()} (possibly {@code null}) + * in its extended data under the key {@link Intent#EXTRA_REFERRER}. + */ + private final Intent mReferrerFillInIntent; private final int mFillInFlags; private final boolean mIsPinned; private final float mModifiedScore; - private final boolean mIsSuspended; - private final Drawable mBadgeIcon; - private final CharSequence mBadgeContentDescription; - @GuardedBy("this") private Drawable mDisplayIcon; - @GuardedBy("this") - private boolean mHasAttemptedIconLoad; - /** Create a new {@link TargetInfo} instance representing a selectable target. */ public static TargetInfo newSelectableTargetInfo( - Context context, @Nullable DisplayResolveInfo sourceInfo, + @Nullable ResolveInfo backupResolveInfo, + Intent resolvedIntent, ChooserTarget chooserTarget, float modifiedScore, - SelectableTargetInfoCommunicator selectableTargetInfoCommunicator, @Nullable ShortcutInfo shortcutInfo, - @Nullable AppTarget appTarget) { + @Nullable AppTarget appTarget, + Intent referrerFillInIntent) { return new SelectableTargetInfo( - context, sourceInfo, + backupResolveInfo, + resolvedIntent, chooserTarget, modifiedScore, - selectableTargetInfoCommunicator, shortcutInfo, - appTarget); + appTarget, + referrerFillInIntent); } private SelectableTargetInfo( - Context context, @Nullable DisplayResolveInfo sourceInfo, + @Nullable ResolveInfo backupResolveInfo, + Intent resolvedIntent, ChooserTarget chooserTarget, float modifiedScore, - SelectableTargetInfoCommunicator selectableTargetInfoComunicator, @Nullable ShortcutInfo shortcutInfo, - @Nullable AppTarget appTarget) { - mContext = context; + @Nullable AppTarget appTarget, + Intent referrerFillInIntent) { mSourceInfo = sourceInfo; mChooserTarget = chooserTarget; mModifiedScore = modifiedScore; - mPm = mContext.getPackageManager(); - mSelectableTargetInfoCommunicator = selectableTargetInfoComunicator; mShortcutInfo = shortcutInfo; mAppTarget = appTarget; mIsPinned = shortcutInfo != null && shortcutInfo.isPinned(); - - final PackageManager pm = mContext.getPackageManager(); - final ApplicationInfo applicationInfo = getApplicationInfoFromSource(sourceInfo); - - mBadgeIcon = (applicationInfo == null) ? null : pm.getApplicationIcon(applicationInfo); - mBadgeContentDescription = - (applicationInfo == null) ? null : pm.getApplicationLabel(applicationInfo); - mIsSuspended = (applicationInfo != null) - && ((applicationInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0); - - if (sourceInfo != null) { - mBackupResolveInfo = null; - } else { - mBackupResolveInfo = - mContext.getPackageManager().resolveActivity(getResolvedIntent(), 0); - } + mBackupResolveInfo = backupResolveInfo; + mResolvedIntent = resolvedIntent; + mReferrerFillInIntent = referrerFillInIntent; mFillInIntent = null; mFillInFlags = 0; @@ -151,25 +132,18 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { } private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) { - mContext = other.mContext; - mPm = other.mPm; - mSelectableTargetInfoCommunicator = other.mSelectableTargetInfoCommunicator; mSourceInfo = other.mSourceInfo; mBackupResolveInfo = other.mBackupResolveInfo; + mResolvedIntent = other.mResolvedIntent; mChooserTarget = other.mChooserTarget; - mBadgeIcon = other.mBadgeIcon; - mBadgeContentDescription = other.mBadgeContentDescription; mShortcutInfo = other.mShortcutInfo; mAppTarget = other.mAppTarget; - mIsSuspended = other.mIsSuspended; - synchronized (other) { - mDisplayIcon = other.mDisplayIcon; - mHasAttemptedIconLoad = other.mHasAttemptedIconLoad; - } + mDisplayIcon = other.mDisplayIcon; mFillInIntent = fillInIntent; mFillInFlags = flags; mModifiedScore = other.mModifiedScore; mIsPinned = other.mIsPinned; + mReferrerFillInIntent = other.mReferrerFillInIntent; mDisplayLabel = sanitizeDisplayLabel(mChooserTarget.getTitle()); } @@ -181,7 +155,7 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { @Override public boolean isSuspended() { - return mIsSuspended; + return (mSourceInfo != null) && mSourceInfo.isSuspended(); } @Override @@ -190,79 +164,6 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { return mSourceInfo; } - /** - * Load display icon, if needed. - */ - @Override - public boolean loadIcon() { - synchronized (this) { - // TODO: evaluating these conditions while `synchronized` ensures that we get consistent - // reads between `mDisplayIcon` and `mHasAttemptedIconLoad`, but doesn't otherwise - // prevent races where two threads might check the conditions (in synchrony) and then - // both go on to load the icon (in parallel, even though one of the loads would be - // redundant, and even though we have no logic to decide which result to keep if they - // differ). This is probably a "safe optimization" in some cases, but our correctness - // can't rely on this eliding the duplicate load, and with a more careful design we - // could probably optimize it out in more cases (or else maybe we should get rid of - // this complexity altogether). - if ((mDisplayIcon != null) || (mShortcutInfo == null) || mHasAttemptedIconLoad) { - return false; - } - } - - Drawable icon = getChooserTargetIconDrawable(mChooserTarget, mShortcutInfo); - if (icon == null) { - return false; - } - - synchronized (this) { - mDisplayIcon = icon; - // TODO: we only end up setting `mHasAttemptedIconLoad` if we were successful in loading - // a (non-null) display icon; in that case, our guard clause above will already - // early-return `false` regardless of `mHasAttemptedIconLoad`. This should be refined, - // or removed if we don't need the extra complexity (including the synchronizaiton?). - mHasAttemptedIconLoad = true; - } - return true; - } - - private Drawable getChooserTargetIconDrawable(ChooserTarget target, - @Nullable ShortcutInfo shortcutInfo) { - Drawable directShareIcon = null; - - // First get the target drawable and associated activity info - final Icon icon = target.getIcon(); - if (icon != null) { - directShareIcon = icon.loadDrawable(mContext); - } else if (shortcutInfo != null) { - LauncherApps launcherApps = (LauncherApps) mContext.getSystemService( - Context.LAUNCHER_APPS_SERVICE); - directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0); - } - - if (directShareIcon == null) return null; - - ActivityInfo info = null; - try { - info = mPm.getActivityInfo(target.getComponentName(), 0); - } catch (PackageManager.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 = mSelectableTargetInfoCommunicator.makePresentationGetter(info) - .getIconBitmap(null); - - // Raster target drawable with appIcon as a badge - SimpleIconFactory sif = SimpleIconFactory.obtain(mContext); - Bitmap directShareBadgedIcon = sif.createAppBadgedIconBitmap(directShareIcon, appIcon); - sif.recycle(); - - return new BitmapDrawable(mContext.getResources(), directShareBadgedIcon); - } - @Override public float getModifiedScore() { return mModifiedScore; @@ -270,14 +171,7 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { @Override public Intent getResolvedIntent() { - if (mSourceInfo != null) { - return mSourceInfo.getResolvedIntent(); - } - - final Intent targetIntent = new Intent(mSelectableTargetInfoCommunicator.getTargetIntent()); - targetIntent.setComponent(mChooserTarget.getComponentName()); - targetIntent.putExtras(mChooserTarget.getIntentExtras()); - return targetIntent; + return mResolvedIntent; } @Override @@ -296,6 +190,11 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { return mChooserTarget.getComponentName(); } + @Nullable + public Icon getChooserTargetIcon() { + return mChooserTarget.getIcon(); + } + private Intent getBaseIntentToSend() { Intent result = getResolvedIntent(); if (result == null) { @@ -305,7 +204,7 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { if (mFillInIntent != null) { result.fillIn(mFillInIntent, mFillInFlags); } - result.fillIn(mSelectableTargetInfoCommunicator.getReferrerFillInIntent(), 0); + result.fillIn(mReferrerFillInIntent, 0); } return result; } @@ -362,16 +261,12 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { } @Override - public synchronized Drawable getDisplayIcon(Context context) { + public Drawable getDisplayIcon() { return mDisplayIcon; } - /** - * @return true if display icon is available - */ - @Override - public synchronized boolean hasDisplayIcon() { - return mDisplayIcon != null; + public void setDisplayIcon(Drawable icon) { + mDisplayIcon = icon; } @Override @@ -418,40 +313,19 @@ public final class SelectableTargetInfo extends ChooserTargetInfo { mMaxHashSaltDays); } - @Nullable - private static ApplicationInfo getApplicationInfoFromSource( - @Nullable DisplayResolveInfo sourceInfo) { - if (sourceInfo == null) { - return null; - } - - final ResolveInfo resolveInfo = sourceInfo.getResolveInfo(); - if (resolveInfo == null) { - return null; - } - - final ActivityInfo activityInfo = resolveInfo.activityInfo; - if (activityInfo == null) { - return null; - } - - return activityInfo.applicationInfo; - } - private static String sanitizeDisplayLabel(CharSequence label) { SpannableStringBuilder sb = new SpannableStringBuilder(label); sb.clearSpans(); return sb.toString(); } + // TODO: merge into ChooserListAdapter.ChooserListCommunicator and delete. /** * Necessary methods to communicate between {@link SelectableTargetInfo} * and {@link ResolverActivity} or {@link ChooserActivity}. */ public interface SelectableTargetInfoCommunicator { - ActivityInfoPresentationGetter makePresentationGetter(ActivityInfo info); - Intent getTargetIntent(); Intent getReferrerFillInIntent(); diff --git a/java/src/com/android/intentresolver/chooser/TargetInfo.java b/java/src/com/android/intentresolver/chooser/TargetInfo.java index 46cd53c6..0e100d4f 100644 --- a/java/src/com/android/intentresolver/chooser/TargetInfo.java +++ b/java/src/com/android/intentresolver/chooser/TargetInfo.java @@ -136,14 +136,16 @@ public interface TargetInfo { /** * @return The drawable that should be used to represent this target including badge - * @param context */ - Drawable getDisplayIcon(Context context); + @Nullable + Drawable getDisplayIcon(); /** * @return true if display icon is available. */ - boolean hasDisplayIcon(); + default boolean hasDisplayIcon() { + return getDisplayIcon() != null; + } /** * Clone this target with the given fill-in information. */ @@ -257,15 +259,6 @@ public interface TargetInfo { } /** - * Attempt to load the display icon, if we have the info for one but it hasn't been loaded yet. - * @return true if an icon may have been loaded as the result of this operation, potentially - * prompting a UI refresh. If this returns false, clients can safely assume there was no change. - */ - default boolean loadIcon() { - return false; - } - - /** * Get more info about this target in the form of a {@link DisplayResolveInfo}, if available. * TODO: this seems to return non-null only for ChooserTargetInfo subclasses. Determine the * meaning of a TargetInfo (ChooserTargetInfo) embedding another kind of TargetInfo |