/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.app;

import static android.content.Context.ACTIVITY_SERVICE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

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.TargetInfo;

import java.util.ArrayList;
import java.util.List;

public class ResolverListAdapter extends BaseAdapter {
    private static final String TAG = "ResolverListAdapter";

    private final List<Intent> mIntents;
    private final Intent[] mInitialIntents;
    private final List<ResolveInfo> mBaseResolveList;
    private final PackageManager mPm;
    protected final Context mContext;
    private final ColorMatrixColorFilter mSuspendedMatrixColorFilter;
    private final boolean mUseLayoutForBrowsables;
    private final int mIconDpi;
    protected ResolveInfo mLastChosen;
    private DisplayResolveInfo mOtherProfile;
    ResolverListController mResolverListController;
    private int mPlaceholderCount;
    private boolean mAllTargetsAreBrowsers = false;

    protected final LayoutInflater mInflater;

    // This one is the list that the Adapter will actually present.
    List<DisplayResolveInfo> mDisplayList;
    private List<ResolvedComponentInfo> mUnfilteredResolveList;

    private int mLastChosenPosition = -1;
    private boolean mFilterLastUsed;
    private final ResolverListCommunicator mResolverListCommunicator;
    private Runnable mPostListReadyRunnable;
    private final boolean mIsAudioCaptureDevice;

    public ResolverListAdapter(Context context, List<Intent> payloadIntents,
            Intent[] initialIntents, List<ResolveInfo> rList,
            boolean filterLastUsed,
            ResolverListController resolverListController,
            boolean useLayoutForBrowsables,
            ResolverListCommunicator resolverListCommunicator,
            boolean isAudioCaptureDevice) {
        mContext = context;
        mIntents = payloadIntents;
        mInitialIntents = initialIntents;
        mBaseResolveList = rList;
        mInflater = LayoutInflater.from(context);
        mPm = context.getPackageManager();
        mDisplayList = new ArrayList<>();
        mFilterLastUsed = filterLastUsed;
        mResolverListController = resolverListController;
        mSuspendedMatrixColorFilter = createSuspendedColorMatrix();
        mUseLayoutForBrowsables = useLayoutForBrowsables;
        mResolverListCommunicator = resolverListCommunicator;
        mIsAudioCaptureDevice = isAudioCaptureDevice;
        final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
        mIconDpi = am.getLauncherLargeIconDensity();
    }

    public void handlePackagesChanged() {
        rebuildList();
        mResolverListCommunicator.onHandlePackagesChanged();
    }

    public void setPlaceholderCount(int count) {
        mPlaceholderCount = count;
    }

    public int getPlaceholderCount() {
        return mPlaceholderCount;
    }

    @Nullable
    public DisplayResolveInfo getFilteredItem() {
        if (mFilterLastUsed && mLastChosenPosition >= 0) {
            // Not using getItem since it offsets to dodge this position for the list
            return mDisplayList.get(mLastChosenPosition);
        }
        return null;
    }

    public DisplayResolveInfo getOtherProfile() {
        return mOtherProfile;
    }

    public int getFilteredPosition() {
        if (mFilterLastUsed && mLastChosenPosition >= 0) {
            return mLastChosenPosition;
        }
        return AbsListView.INVALID_POSITION;
    }

    public boolean hasFilteredItem() {
        return mFilterLastUsed && mLastChosen != null;
    }

    public float getScore(DisplayResolveInfo target) {
        return mResolverListController.getScore(target);
    }

    public void updateModel(ComponentName componentName) {
        mResolverListController.updateModel(componentName);
    }

    public void updateChooserCounts(String packageName, int userId, String action) {
        mResolverListController.updateChooserCounts(packageName, userId, action);
    }

    List<ResolvedComponentInfo> getUnfilteredResolveList() {
        return mUnfilteredResolveList;
    }

    /**
     * @return true if all items in the display list are defined as browsers by
     *         ResolveInfo.handleAllWebDataURI
     */
    public boolean areAllTargetsBrowsers() {
        return mAllTargetsAreBrowsers;
    }

    /**
     * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
     * to complete.
     *
     * @return Whether or not the list building is completed.
     */
    protected boolean rebuildList() {
        List<ResolvedComponentInfo> currentResolveList = null;
        // Clear the value of mOtherProfile from previous call.
        mOtherProfile = null;
        mLastChosen = null;
        mLastChosenPosition = -1;
        mAllTargetsAreBrowsers = false;
        mDisplayList.clear();
        if (mBaseResolveList != null) {
            currentResolveList = mUnfilteredResolveList = new ArrayList<>();
            mResolverListController.addResolveListDedupe(currentResolveList,
                    mResolverListCommunicator.getTargetIntent(),
                    mBaseResolveList);
        } else {
            currentResolveList = mUnfilteredResolveList =
                    mResolverListController.getResolversForIntent(shouldGetResolvedFilter(),
                            mResolverListCommunicator.shouldGetActivityMetadata(),
                            mIntents);
            if (currentResolveList == null) {
                processSortedList(currentResolveList);
                return true;
            }
            List<ResolvedComponentInfo> originalList =
                    mResolverListController.filterIneligibleActivities(currentResolveList,
                            true);
            if (originalList != null) {
                mUnfilteredResolveList = originalList;
            }
        }

        // So far we only support a single other profile at a time.
        // The first one we see gets special treatment.
        for (ResolvedComponentInfo info : currentResolveList) {
            ResolveInfo resolveInfo = info.getResolveInfoAt(0);
            if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) {
                Intent pOrigIntent = mResolverListCommunicator.getReplacementIntent(
                        resolveInfo.activityInfo,
                        info.getIntentAt(0));
                Intent replacementIntent = mResolverListCommunicator.getReplacementIntent(
                        resolveInfo.activityInfo,
                        mResolverListCommunicator.getTargetIntent());
                mOtherProfile = new DisplayResolveInfo(info.getIntentAt(0),
                        resolveInfo,
                        resolveInfo.loadLabel(mPm),
                        resolveInfo.loadLabel(mPm),
                        pOrigIntent != null ? pOrigIntent : replacementIntent,
                        makePresentationGetter(resolveInfo));
                currentResolveList.remove(info);
                break;
            }
        }

        if (mOtherProfile == null) {
            try {
                mLastChosen = mResolverListController.getLastChosen();
            } catch (RemoteException re) {
                Log.d(TAG, "Error calling getLastChosenActivity\n" + re);
            }
        }

        int n;
        if ((currentResolveList != null) && ((n = currentResolveList.size()) > 0)) {
            // We only care about fixing the unfilteredList if the current resolve list and
            // current resolve list are currently the same.
            List<ResolvedComponentInfo> originalList =
                    mResolverListController.filterLowPriority(currentResolveList,
                            mUnfilteredResolveList == currentResolveList);
            if (originalList != null) {
                mUnfilteredResolveList = originalList;
            }

            if (currentResolveList.size() > 1) {
                int placeholderCount = currentResolveList.size();
                if (mResolverListCommunicator.useLayoutWithDefault()) {
                    --placeholderCount;
                }
                setPlaceholderCount(placeholderCount);
                createSortingTask().execute(currentResolveList);
                postListReadyRunnable();
                return false;
            } else {
                processSortedList(currentResolveList);
                return true;
            }
        } else {
            processSortedList(currentResolveList);
            return true;
        }
    }

    AsyncTask<List<ResolvedComponentInfo>,
            Void,
            List<ResolvedComponentInfo>> createSortingTask() {
        return new AsyncTask<List<ResolvedComponentInfo>,
                Void,
                List<ResolvedComponentInfo>>() {
            @Override
            protected List<ResolvedComponentInfo> doInBackground(
                    List<ResolvedComponentInfo>... params) {
                mResolverListController.sort(params[0]);
                return params[0];
            }
            @Override
            protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
                processSortedList(sortedComponents);
                mResolverListCommunicator.updateProfileViewButton();
                notifyDataSetChanged();
            }
        };
    }


    protected void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
        int n;
        if (sortedComponents != null && (n = sortedComponents.size()) != 0) {
            mAllTargetsAreBrowsers = mUseLayoutForBrowsables;

            // First put the initial items at the top.
            if (mInitialIntents != null) {
                for (int i = 0; i < mInitialIntents.length; i++) {
                    Intent ii = mInitialIntents[i];
                    if (ii == null) {
                        continue;
                    }
                    ActivityInfo ai = ii.resolveActivityInfo(
                            mPm, 0);
                    if (ai == null) {
                        Log.w(TAG, "No activity found for " + ii);
                        continue;
                    }
                    ResolveInfo ri = new ResolveInfo();
                    ri.activityInfo = ai;
                    UserManager userManager =
                            (UserManager) mContext.getSystemService(Context.USER_SERVICE);
                    if (ii instanceof LabeledIntent) {
                        LabeledIntent li = (LabeledIntent) ii;
                        ri.resolvePackageName = li.getSourcePackage();
                        ri.labelRes = li.getLabelResource();
                        ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                        ri.icon = li.getIconResource();
                        ri.iconResourceId = ri.icon;
                    }
                    if (userManager.isManagedProfile()) {
                        ri.noResourceId = true;
                        ri.icon = 0;
                    }
                    mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;

                    addResolveInfo(new DisplayResolveInfo(ii, ri,
                            ri.loadLabel(mPm), null, ii, makePresentationGetter(ri)));
                }
            }


            for (ResolvedComponentInfo rci : sortedComponents) {
                final ResolveInfo ri = rci.getResolveInfoAt(0);
                if (ri != null) {
                    mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
                    addResolveInfoWithAlternates(rci);
                }
            }
        }

        mResolverListCommunicator.sendVoiceChoicesIfNeeded();
        postListReadyRunnable();
    }

    /**
     * Some necessary methods for creating the list are initiated in onCreate and will also
     * determine the layout known. We therefore can't update the UI inline and post to the
     * handler thread to update after the current task is finished.
     */
    private void postListReadyRunnable() {
        if (mPostListReadyRunnable == null) {
            mPostListReadyRunnable = new Runnable() {
                @Override
                public void run() {
                    mResolverListCommunicator.onPostListReady();
                    mPostListReadyRunnable = null;
                }
            };
            mContext.getMainThreadHandler().post(mPostListReadyRunnable);
        }
    }

    public boolean shouldGetResolvedFilter() {
        return mFilterLastUsed;
    }

    private void addResolveInfoWithAlternates(ResolvedComponentInfo rci) {
        final int count = rci.getCount();
        final Intent intent = rci.getIntentAt(0);
        final ResolveInfo add = rci.getResolveInfoAt(0);
        final Intent replaceIntent =
                mResolverListCommunicator.getReplacementIntent(add.activityInfo, intent);
        final Intent defaultIntent = mResolverListCommunicator.getReplacementIntent(
                add.activityInfo, mResolverListCommunicator.getTargetIntent());
        final DisplayResolveInfo
                dri = new DisplayResolveInfo(intent, add,
                replaceIntent != null ? replaceIntent : defaultIntent, makePresentationGetter(add));
        dri.setPinned(rci.isPinned());
        if (rci.isPinned()) {
            Log.i(TAG, "Pinned item: " + rci.name);
        }
        addResolveInfo(dri);
        if (replaceIntent == intent) {
            // Only add alternates if we didn't get a specific replacement from
            // the caller. If we have one it trumps potential alternates.
            for (int i = 1, n = count; i < n; i++) {
                final Intent altIntent = rci.getIntentAt(i);
                dri.addAlternateSourceIntent(altIntent);
            }
        }
        updateLastChosenPosition(add);
    }

    private void updateLastChosenPosition(ResolveInfo info) {
        // If another profile is present, ignore the last chosen entry.
        if (mOtherProfile != null) {
            mLastChosenPosition = -1;
            return;
        }
        if (mLastChosen != null
                && mLastChosen.activityInfo.packageName.equals(info.activityInfo.packageName)
                && mLastChosen.activityInfo.name.equals(info.activityInfo.name)) {
            mLastChosenPosition = mDisplayList.size() - 1;
        }
    }

    // We assume that at this point we've already filtered out the only intent for a different
    // targetUserId which we're going to use.
    private void addResolveInfo(DisplayResolveInfo dri) {
        if (dri != null && dri.getResolveInfo() != null
                && dri.getResolveInfo().targetUserId == UserHandle.USER_CURRENT) {
            // Checks if this info is already listed in display.
            for (DisplayResolveInfo existingInfo : mDisplayList) {
                if (mResolverListCommunicator
                        .resolveInfoMatch(dri.getResolveInfo(), existingInfo.getResolveInfo())) {
                    return;
                }
            }
            mDisplayList.add(dri);
        }
    }

    @Nullable
    public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
        TargetInfo target = targetInfoForPosition(position, filtered);
        if (target != null) {
            return target.getResolveInfo();
        }
        return null;
    }

    @Nullable
    public TargetInfo targetInfoForPosition(int position, boolean filtered) {
        if (filtered) {
            return getItem(position);
        }
        if (mDisplayList.size() > position) {
            return mDisplayList.get(position);
        }
        return null;
    }

    public int getCount() {
        int totalSize = mDisplayList == null || mDisplayList.isEmpty() ? mPlaceholderCount :
                mDisplayList.size();
        if (mFilterLastUsed && mLastChosenPosition >= 0) {
            totalSize--;
        }
        return totalSize;
    }

    public int getUnfilteredCount() {
        return mDisplayList.size();
    }

    @Nullable
    public TargetInfo getItem(int position) {
        if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) {
            position++;
        }
        if (mDisplayList.size() > position) {
            return mDisplayList.get(position);
        } else {
            return null;
        }
    }

    public long getItemId(int position) {
        return position;
    }

    public int getDisplayResolveInfoCount() {
        return mDisplayList.size();
    }

    public DisplayResolveInfo getDisplayResolveInfo(int index) {
        // Used to query services. We only query services for primary targets, not alternates.
        return mDisplayList.get(index);
    }

    public final View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            view = createView(parent);
        }
        onBindView(view, getItem(position));
        return view;
    }

    public final View createView(ViewGroup parent) {
        final View view = onCreateView(parent);
        final ViewHolder holder = new ViewHolder(view);
        view.setTag(holder);
        return view;
    }

    View onCreateView(ViewGroup parent) {
        return mInflater.inflate(
                com.android.internal.R.layout.resolve_list_item, parent, false);
    }

    public final void bindView(int position, View view) {
        onBindView(view, getItem(position));
    }

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

        if (info instanceof DisplayResolveInfo
                && !((DisplayResolveInfo) info).hasDisplayLabel()) {
            getLoadLabelTask((DisplayResolveInfo) info, holder).execute();
        } else {
            holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo());
        }

        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();
        } else {
            holder.icon.setImageDrawable(info.getDisplayIcon(mContext));
        }
    }

    protected LoadLabelTask getLoadLabelTask(DisplayResolveInfo info, ViewHolder holder) {
        return new LoadLabelTask(info, holder);
    }

    public void onDestroy() {
        if (mPostListReadyRunnable != null) {
            mContext.getMainThreadHandler().removeCallbacks(mPostListReadyRunnable);
            mPostListReadyRunnable = null;
        }
        if (mResolverListController != null) {
            mResolverListController.destroy();
        }
    }

    private ColorMatrixColorFilter createSuspendedColorMatrix() {
        int grayValue = 127;
        float scale = 0.5f; // half bright

        ColorMatrix tempBrightnessMatrix = new ColorMatrix();
        float[] mat = tempBrightnessMatrix.getArray();
        mat[0] = scale;
        mat[6] = scale;
        mat[12] = scale;
        mat[4] = grayValue;
        mat[9] = grayValue;
        mat[14] = grayValue;

        ColorMatrix matrix = new ColorMatrix();
        matrix.setSaturation(0.0f);
        matrix.preConcat(tempBrightnessMatrix);
        return new ColorMatrixColorFilter(matrix);
    }

    ActivityInfoPresentationGetter makePresentationGetter(ActivityInfo ai) {
        return new ActivityInfoPresentationGetter(mContext, mIconDpi, ai);
    }

    ResolveInfoPresentationGetter makePresentationGetter(ResolveInfo ri) {
        return new ResolveInfoPresentationGetter(mContext, mIconDpi, ri);
    }

    Drawable loadIconForResolveInfo(ResolveInfo ri) {
        // Load icons based on the current process. If in work profile icons should be badged.
        return makePresentationGetter(ri).getIcon(mResolverListController.getUserHandle());
    }

    void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
        final DisplayResolveInfo iconInfo = getFilteredItem();
        if (iconView != null && iconInfo != null) {
            new LoadIconTask(iconInfo, iconView).execute();
        }
    }

    /**
     * Necessary methods to communicate between {@link ResolverListAdapter}
     * and {@link ResolverActivity}.
     */
    interface ResolverListCommunicator {

        boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs);

        Intent getReplacementIntent(ActivityInfo activityInfo, Intent defIntent);

        void onPostListReady();

        void sendVoiceChoicesIfNeeded();

        void updateProfileViewButton();

        boolean useLayoutWithDefault();

        boolean shouldGetActivityMetadata();

        Intent getTargetIntent();

        void onHandlePackagesChanged();
    }

    static class ViewHolder {
        public View itemView;
        public Drawable defaultItemViewBackground;

        public TextView text;
        public TextView text2;
        public ImageView icon;

        ViewHolder(View view) {
            itemView = view;
            defaultItemViewBackground = view.getBackground();
            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);
        }

        public void bindLabel(CharSequence label, CharSequence subLabel) {
            if (!TextUtils.equals(text.getText(), label)) {
                text.setText(label);
            }

            // Always show a subLabel for visual consistency across list items. Show an empty
            // subLabel if the subLabel is the same as the label
            if (TextUtils.equals(label, subLabel)) {
                subLabel = null;
            }

            if (!TextUtils.equals(text2.getText(), subLabel)) {
                text2.setVisibility(View.VISIBLE);
                text2.setText(subLabel);
            }
        }
    }

    protected class LoadLabelTask extends AsyncTask<Void, Void, CharSequence[]> {
        private final DisplayResolveInfo mDisplayResolveInfo;
        private final ViewHolder mHolder;

        protected LoadLabelTask(DisplayResolveInfo dri, ViewHolder holder) {
            mDisplayResolveInfo = dri;
            mHolder = holder;
        }

        @Override
        protected CharSequence[] doInBackground(Void... voids) {
            ResolveInfoPresentationGetter pg =
                    makePresentationGetter(mDisplayResolveInfo.getResolveInfo());

            if (mIsAudioCaptureDevice) {
                // This is an audio capture device, so check record permissions
                ActivityInfo activityInfo = mDisplayResolveInfo.getResolveInfo().activityInfo;
                String packageName = activityInfo.packageName;

                int uid = activityInfo.applicationInfo.uid;
                boolean hasRecordPermission =
                        PermissionChecker.checkPermissionForPreflight(
                                mContext,
                                android.Manifest.permission.RECORD_AUDIO, -1, uid,
                                packageName)
                                == android.content.pm.PackageManager.PERMISSION_GRANTED;

                if (!hasRecordPermission) {
                    // Doesn't have record permission, so warn the user
                    return new CharSequence[] {
                            pg.getLabel(),
                            mContext.getString(R.string.usb_device_resolve_prompt_warn)
                    };
                }
            }

            return new CharSequence[] {
                    pg.getLabel(),
                    pg.getSubLabel()
            };
        }

        @Override
        protected void onPostExecute(CharSequence[] result) {
            mDisplayResolveInfo.setDisplayLabel(result[0]);
            mDisplayResolveInfo.setExtendedInfo(result[1]);
            mHolder.bindLabel(result[0], result[1]);
        }
    }

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

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

        @Override
        protected Drawable doInBackground(Void... params) {
            return loadIconForResolveInfo(mResolveInfo);
        }

        @Override
        protected void onPostExecute(Drawable d) {
            if (getOtherProfile() == mDisplayResolveInfo) {
                mResolverListCommunicator.updateProfileViewButton();
            } else {
                mDisplayResolveInfo.setDisplayIcon(d);
                mTargetView.setImageDrawable(d);
            }
        }
    }

    /**
     * Loads the icon and label for the provided ResolveInfo.
     */
    @VisibleForTesting
    public static class ResolveInfoPresentationGetter extends ActivityInfoPresentationGetter {
        private final ResolveInfo mRi;
        public ResolveInfoPresentationGetter(Context ctx, int iconDpi, ResolveInfo ri) {
            super(ctx, iconDpi, ri.activityInfo);
            mRi = ri;
        }

        @Override
        Drawable getIconSubstituteInternal() {
            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 (PackageManager.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 ActivityInfo if no icon is found via ResolveInfo
            if (dr == null) dr = super.getIconSubstituteInternal();

            return dr;
        }

        @Override
        String getAppSubLabelInternal() {
            // Will default to app name if no intent filter or activity label set, make sure to
            // check if subLabel matches label before final display
            return (String) mRi.loadLabel(mPm);
        }
    }

    /**
     * Loads the icon and label for the provided ActivityInfo.
     */
    @VisibleForTesting
    public static class ActivityInfoPresentationGetter extends
            TargetPresentationGetter {
        private final ActivityInfo mActivityInfo;
        public ActivityInfoPresentationGetter(Context ctx, int iconDpi,
                ActivityInfo activityInfo) {
            super(ctx, iconDpi, activityInfo.applicationInfo);
            mActivityInfo = activityInfo;
        }

        @Override
        Drawable getIconSubstituteInternal() {
            Drawable dr = null;
            try {
                // Do not use ActivityInfo#getIconResource() as it defaults to the app
                if (mActivityInfo.icon != 0) {
                    dr = loadIconFromResource(
                            mPm.getResourcesForApplication(mActivityInfo.applicationInfo),
                            mActivityInfo.icon);
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON permission granted but "
                        + "couldn't find resources for package", e);
            }

            return dr;
        }

        @Override
        String getAppSubLabelInternal() {
            // Will default to app name if no activity label set, make sure to check if subLabel
            // matches label before final display
            return (String) mActivityInfo.loadLabel(mPm);
        }
    }

    /**
     * Loads the icon and label for the provided ApplicationInfo. Defaults to using the application
     * icon and label over any IntentFilter or Activity icon to increase user understanding, with an
     * exception for applications that hold the right permission. Always attempts to use available
     * resources over PackageManager loading mechanisms so badging can be done by iconloader. Uses
     * Strings to strip creative formatting.
     */
    private abstract static class TargetPresentationGetter {
        @Nullable abstract Drawable getIconSubstituteInternal();
        @Nullable abstract String getAppSubLabelInternal();

        private Context mCtx;
        private final int mIconDpi;
        private final boolean mHasSubstitutePermission;
        private final ApplicationInfo mAi;

        protected PackageManager mPm;

        TargetPresentationGetter(Context ctx, int iconDpi, ApplicationInfo ai) {
            mCtx = ctx;
            mPm = ctx.getPackageManager();
            mAi = ai;
            mIconDpi = iconDpi;
            mHasSubstitutePermission = PackageManager.PERMISSION_GRANTED == mPm.checkPermission(
                    android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON,
                    mAi.packageName);
        }

        public Drawable getIcon(UserHandle userHandle) {
            return new BitmapDrawable(mCtx.getResources(), getIconBitmap(userHandle));
        }

        public Bitmap getIconBitmap(UserHandle userHandle) {
            Drawable dr = null;
            if (mHasSubstitutePermission) {
                dr = getIconSubstituteInternal();
            }

            if (dr == null) {
                try {
                    if (mAi.icon != 0) {
                        dr = loadIconFromResource(mPm.getResourcesForApplication(mAi), mAi.icon);
                    }
                } catch (PackageManager.NameNotFoundException ignore) {
                }
            }

            // Fall back to ApplicationInfo#loadIcon if nothing has been loaded
            if (dr == null) {
                dr = mAi.loadIcon(mPm);
            }

            SimpleIconFactory sif = SimpleIconFactory.obtain(mCtx);
            Bitmap icon = sif.createUserBadgedIconBitmap(dr, userHandle);
            sif.recycle();

            return icon;
        }

        public String getLabel() {
            String label = null;
            // Apps with the substitute permission will always show the sublabel as their label
            if (mHasSubstitutePermission) {
                label = getAppSubLabelInternal();
            }

            if (label == null) {
                label = (String) mAi.loadLabel(mPm);
            }

            return label;
        }

        public String getSubLabel() {
            // Apps with the substitute permission will never have a sublabel
            if (mHasSubstitutePermission) return null;
            return getAppSubLabelInternal();
        }

        protected String loadLabelFromResource(Resources res, int resId) {
            return res.getString(resId);
        }

        @Nullable
        protected Drawable loadIconFromResource(Resources res, int resId) {
            return res.getDrawableForDensity(resId, mIconDpi);
        }

    }
}
