Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 563d7b9d authored by Matt Pietal's avatar Matt Pietal
Browse files

Sharesheet - Cache loading of icons

For sharesheet, assume that the reordering of elements will make the
last assigned ViewHolder invalid for async icon loading. If we already
have an async task for the particular ResolveInfo, update the
ViewHolder target when it's complete.

Fixes: 158172791
Test: atest ChooserActivityTest ResolverActivityTest
Change-Id: I0ea9f443512f91e8fa4c5d6b72a35e9231e69e51
parent 827c121e
Loading
Loading
Loading
Loading
+35 −3
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
            mSelectableTargetInfoCommunicator;

    private int mNumShortcutResults = 0;
    private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();

    // Reserve spots for incoming direct share targets by adding placeholders
    private ChooserTargetInfo
@@ -239,11 +240,42 @@ public class ChooserListAdapter extends ResolverListAdapter {

    @Override
    protected void onBindView(View view, TargetInfo info, int position) {
        super.onBindView(view, info, position);
        if (info == null) return;
        final ViewHolder holder = (ViewHolder) view.getTag();
        if (info == null) {
            holder.icon.setImageDrawable(
                    mContext.getDrawable(R.drawable.resolver_icon_placeholder));
            return;
        }

        if (!(info instanceof DisplayResolveInfo)) {
            holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel());
            holder.bindIcon(info);

            if (info instanceof SelectableTargetInfo) {
                // direct share targets should append the application name for a better readout
                DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo();
                CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : "";
                CharSequence extendedInfo = info.getExtendedInfo();
                String contentDescription = String.join(" ", info.getDisplayLabel(),
                        extendedInfo != null ? extendedInfo : "", appName);
                holder.updateContentDescription(contentDescription);
            }
        } else {
            DisplayResolveInfo dri = (DisplayResolveInfo) info;
            holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel());
            LoadIconTask task = mIconLoaders.get(dri);
            if (task == null) {
                task = new LoadIconTask(dri, holder);
                mIconLoaders.put(dri, task);
                task.execute();
            } else {
                // The holder was potentially changed as the underlying items were
                // reshuffled, so reset the target holder
                task.setViewHolder(holder);
            }
        }

        // If target is loading, show a special placeholder shape in the label, make unclickable
        final ViewHolder holder = (ViewHolder) view.getTag();
        if (info instanceof ChooserActivity.PlaceHolderTargetInfo) {
            final int maxWidth = mContext.getResources().getDimensionPixelSize(
                    R.dimen.chooser_direct_share_label_placeholder_max_width);
+52 −41
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.SelectableTargetInfo;
import com.android.internal.app.chooser.TargetInfo;

import java.util.ArrayList;
@@ -68,7 +67,7 @@ public class ResolverListAdapter extends BaseAdapter {
    private final List<ResolveInfo> mBaseResolveList;
    private final PackageManager mPm;
    protected final Context mContext;
    private final ColorMatrixColorFilter mSuspendedMatrixColorFilter;
    private static ColorMatrixColorFilter sSuspendedMatrixColorFilter;
    private final int mIconDpi;
    protected ResolveInfo mLastChosen;
    private DisplayResolveInfo mOtherProfile;
@@ -103,7 +102,6 @@ public class ResolverListAdapter extends BaseAdapter {
        mDisplayList = new ArrayList<>();
        mFilterLastUsed = filterLastUsed;
        mResolverListController = resolverListController;
        mSuspendedMatrixColorFilter = createSuspendedColorMatrix();
        mResolverListCommunicator = resolverListCommunicator;
        mIsAudioCaptureDevice = isAudioCaptureDevice;
        final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
@@ -541,28 +539,13 @@ public class ResolverListAdapter extends BaseAdapter {
            getLoadLabelTask((DisplayResolveInfo) info, holder).execute();
        } else {
            holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel());
            if (info instanceof SelectableTargetInfo) {
                // direct share targets should append the application name for a better readout
                DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo();
                CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : "";
                CharSequence extendedInfo = info.getExtendedInfo();
                String contentDescription = String.join(" ", info.getDisplayLabel(),
                        extendedInfo != null ? extendedInfo : "", appName);
                holder.updateContentDescription(contentDescription);
            }
        }

        if (info.isSuspended()) {
            holder.icon.setColorFilter(mSuspendedMatrixColorFilter);
        } else {
            holder.icon.setColorFilter(null);
        }

        if (info instanceof DisplayResolveInfo
                && !((DisplayResolveInfo) info).hasDisplayIcon()) {
            new ResolverListAdapter.LoadIconTask((DisplayResolveInfo) info, holder.icon).execute();
            new LoadIconTask((DisplayResolveInfo) info, holder).execute();
        } else {
            holder.icon.setImageDrawable(info.getDisplayIcon(mContext));
            holder.bindIcon(info);
        }
    }

@@ -580,7 +563,9 @@ public class ResolverListAdapter extends BaseAdapter {
        }
    }

    private ColorMatrixColorFilter createSuspendedColorMatrix() {
    private static ColorMatrixColorFilter getSuspendedColorMatrix() {
        if (sSuspendedMatrixColorFilter == null) {

            int grayValue = 127;
            float scale = 0.5f; // half bright

@@ -596,7 +581,9 @@ public class ResolverListAdapter extends BaseAdapter {
            ColorMatrix matrix = new ColorMatrix();
            matrix.setSaturation(0.0f);
            matrix.preConcat(tempBrightnessMatrix);
        return new ColorMatrixColorFilter(matrix);
            sSuspendedMatrixColorFilter = new ColorMatrixColorFilter(matrix);
        }
        return sSuspendedMatrixColorFilter;
    }

    ActivityInfoPresentationGetter makePresentationGetter(ActivityInfo ai) {
@@ -615,7 +602,17 @@ public class ResolverListAdapter extends BaseAdapter {
    void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
        final DisplayResolveInfo iconInfo = getFilteredItem();
        if (iconView != null && iconInfo != null) {
            new LoadIconTask(iconInfo, iconView).execute();
            new AsyncTask<Void, Void, Drawable>() {
                @Override
                protected Drawable doInBackground(Void... params) {
                    return loadIconForResolveInfo(iconInfo.getResolveInfo());
                }

                @Override
                protected void onPostExecute(Drawable d) {
                    iconView.setImageDrawable(d);
                }
            }.execute();
        }
    }

@@ -708,6 +705,15 @@ public class ResolverListAdapter extends BaseAdapter {
        public void updateContentDescription(String description) {
            itemView.setContentDescription(description);
        }

        public void bindIcon(TargetInfo info) {
            icon.setImageDrawable(info.getDisplayIcon(itemView.getContext()));
            if (info.isSuspended()) {
                icon.setColorFilter(getSuspendedColorMatrix());
            } else {
                icon.setColorFilter(null);
            }
        }
    }

    protected class LoadLabelTask extends AsyncTask<Void, Void, CharSequence[]> {
@@ -761,14 +767,14 @@ public class ResolverListAdapter extends BaseAdapter {
    }

    class LoadIconTask extends AsyncTask<Void, Void, Drawable> {
        protected final com.android.internal.app.chooser.DisplayResolveInfo mDisplayResolveInfo;
        protected final DisplayResolveInfo mDisplayResolveInfo;
        private final ResolveInfo mResolveInfo;
        private final ImageView mTargetView;
        private ViewHolder mHolder;

        LoadIconTask(DisplayResolveInfo dri, ImageView target) {
        LoadIconTask(DisplayResolveInfo dri, ViewHolder holder) {
            mDisplayResolveInfo = dri;
            mResolveInfo = dri.getResolveInfo();
            mTargetView = target;
            mHolder = holder;
        }

        @Override
@@ -782,8 +788,13 @@ public class ResolverListAdapter extends BaseAdapter {
                mResolverListCommunicator.updateProfileViewButton();
            } else {
                mDisplayResolveInfo.setDisplayIcon(d);
                mTargetView.setImageDrawable(d);
                mHolder.bindIcon(mDisplayResolveInfo);
            }
        }

        public void setViewHolder(ViewHolder holder) {
            mHolder = holder;
            mHolder.bindIcon(mDisplayResolveInfo);
        }
    }