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

Commit 3e0f0920 authored by Alison Cichowlas's avatar Alison Cichowlas Committed by android-build-merger
Browse files

Merge "Restore app pinning." into qt-qpr1-dev

am: 599634a2

Change-Id: I808d010ea658badb7aaecc4a62074a18ae97f7d0
parents dd1cd697 599634a2
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.util.Log;

import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -37,7 +38,7 @@ import java.util.List;
/**
 * Used to sort resolved activities in {@link ResolverListController}.
 */
abstract class AbstractResolverComparator implements Comparator<ResolvedComponentInfo> {
public abstract class AbstractResolverComparator implements Comparator<ResolvedComponentInfo> {

    private static final int NUM_OF_TOP_ANNOTATIONS_TO_USE = 3;
    private static final boolean DEBUG = false;
@@ -62,6 +63,8 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
    // predicting ranking scores.
    private static final int WATCHDOG_TIMEOUT_MILLIS = 500;

    private final Comparator<ResolveInfo> mAzComparator;

    protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
@@ -90,7 +93,7 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
        }
    };

    AbstractResolverComparator(Context context, Intent intent) {
    public AbstractResolverComparator(Context context, Intent intent) {
        String scheme = intent.getScheme();
        mHttp = "http".equals(scheme) || "https".equals(scheme);
        mContentType = intent.getType();
@@ -100,6 +103,7 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
        mDefaultBrowserPackageName = mHttp
                ? mPm.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId())
                : null;
        mAzComparator = new AzInfoComparator(context);
    }

    // get annotations of content from intent.
@@ -168,6 +172,20 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
                return lhsSpecific ? -1 : 1;
            }
        }

        final boolean lPinned = lhsp.isPinned();
        final boolean rPinned = rhsp.isPinned();

        // Pinned items always receive priority.
        if (lPinned && !rPinned) {
            return -1;
        } else if (!lPinned && rPinned) {
            return 1;
        } else if (lPinned && rPinned) {
            // If both items are pinned, resolve the tie alphabetically.
            return mAzComparator.compare(lhsp.getResolveInfoAt(0), rhsp.getResolveInfoAt(0));
        }

        return compare(lhs, rhs);
    }

@@ -258,4 +276,25 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
        }
        return false;
    }

    /**
     * Sort intents alphabetically based on package name.
     */
    class AzInfoComparator implements Comparator<ResolveInfo> {
        Collator mCollator;
        AzInfoComparator(Context context) {
            mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
        }

        @Override
        public int compare(ResolveInfo lhsp, ResolveInfo rhsp) {
            if (lhsp == null) {
                return -1;
            } else if (rhsp == null) {
                return 1;
            }
            return mCollator.compare(lhsp.activityInfo.packageName, rhsp.activityInfo.packageName);
        }
    }

}
+42 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
@@ -69,6 +70,7 @@ import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -78,6 +80,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.DocumentsContract;
import android.provider.Downloads;
@@ -120,6 +123,7 @@ import com.android.internal.widget.ResolverDrawerLayout;

import com.google.android.collect.Lists;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -256,6 +260,9 @@ public class ChooserActivity extends ResolverActivity {
    private static final int MAX_EXTRA_INITIAL_INTENTS = 2;
    private static final int MAX_EXTRA_CHOOSER_TARGETS = 2;

    private SharedPreferences mPinnedSharedPrefs;
    private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings";

    private boolean mListViewDataChanged = false;

    @Retention(SOURCE)
@@ -600,6 +607,8 @@ public class ChooserActivity extends ResolverActivity {
                Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
        setSafeForwardingMode(true);

        mPinnedSharedPrefs = getPinnedSharedPrefs(this);

        pa = intent.getParcelableArrayExtra(Intent.EXTRA_EXCLUDE_COMPONENTS);
        if (pa != null) {
            ComponentName[] names = new ComponentName[pa.length];
@@ -731,6 +740,23 @@ public class ChooserActivity extends ResolverActivity {
        }
    }


    static SharedPreferences getPinnedSharedPrefs(Context context) {
        // The code below is because in the android:ui process, no one can hear you scream.
        // The package info in the context isn't initialized in the way it is for normal apps,
        // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
        // build the path manually below using the same policy that appears in ContextImpl.
        // This fails silently under the hood if there's a problem, so if we find ourselves in
        // the case where we don't have access to credential encrypted storage we just won't
        // have our pinned target info.
        final File prefsFile = new File(new File(
                Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
                        context.getUserId(), context.getPackageName()),
                "shared_prefs"),
                PINNED_SHARED_PREFS_NAME + ".xml");
        return context.getSharedPreferences(prefsFile, MODE_PRIVATE);
    }

    /**
     * Returns true if app prediction service is defined and the component exists on device.
     */
@@ -1277,9 +1303,10 @@ public class ChooserActivity extends ResolverActivity {
        }

        ComponentName name = ri.activityInfo.getComponentName();
        boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
        ResolverTargetActionsDialogFragment f =
                new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()),
                        name);
                    name, pinned);
        f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
    }

@@ -1956,6 +1983,12 @@ public class ChooserActivity extends ResolverActivity {
            }
            return false;
        }

        @Override
        public boolean isComponentPinned(ComponentName name) {
            return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
        }

    }

    @Override
@@ -2089,6 +2122,10 @@ public class ChooserActivity extends ResolverActivity {
        public boolean isSuspended() {
            return false;
        }

        public boolean isPinned() {
            return false;
        }
    }

    final class PlaceHolderTargetInfo extends NotSelectableTargetInfo {
@@ -2177,6 +2214,10 @@ public class ChooserActivity extends ResolverActivity {
            return mIsSuspended;
        }

        public boolean isPinned() {
            return mSourceInfo != null && mSourceInfo.isPinned();
        }

        /**
         * Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip
         * the call to LauncherApps#getShortcuts(ShortcutQuery).
+29 −0
Original line number Diff line number Diff line
@@ -1417,6 +1417,7 @@ public class ResolverActivity extends Activity {
        private final Intent mResolvedIntent;
        private final List<Intent> mSourceIntents = new ArrayList<>();
        private boolean mIsSuspended;
        private boolean mPinned = false;

        public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                CharSequence pInfo, Intent pOrigIntent) {
@@ -1520,6 +1521,15 @@ public class ResolverActivity extends Activity {
        public boolean isSuspended() {
            return mIsSuspended;
        }

        @Override
        public boolean isPinned() {
            return mPinned;
        }

        public void setPinned(boolean pinned) {
            mPinned = pinned;
        }
    }

    List<DisplayResolveInfo> getDisplayList() {
@@ -1620,6 +1630,11 @@ public class ResolverActivity extends Activity {
          * @return true if this target can be selected by the user
          */
        boolean isSuspended();

        /**
         * @return true if this target should be pinned to the front by the request of the user
         */
        boolean isPinned();
    }

    public class ResolveListAdapter extends BaseAdapter {
@@ -1926,6 +1941,10 @@ public class ResolverActivity extends Activity {
            final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
            final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
                    extraInfo, replaceIntent);
            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
@@ -2094,6 +2113,7 @@ public class ResolverActivity extends Activity {
        public final ComponentName name;
        private final List<Intent> mIntents = new ArrayList<>();
        private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
        private boolean mPinned;

        public ResolvedComponentInfo(ComponentName name, Intent intent, ResolveInfo info) {
            this.name = name;
@@ -2134,6 +2154,15 @@ public class ResolverActivity extends Activity {
            }
            return -1;
        }

        public boolean isPinned() {
            return mPinned;
        }

        public void setPinned(boolean pinned) {
            mPinned = pinned;
        }

    }

    static class ViewHolder {
+11 −0
Original line number Diff line number Diff line
@@ -156,11 +156,22 @@ public class ResolverListController {
                        newInfo.activityInfo.packageName, newInfo.activityInfo.name);
                final ResolverActivity.ResolvedComponentInfo rci =
                        new ResolverActivity.ResolvedComponentInfo(name, intent, newInfo);
                rci.setPinned(isComponentPinned(name));
                into.add(rci);
            }
        }
    }


    /**
     * Whether this component is pinned by the user. Always false for resolver; overridden in
     * Chooser.
     */
    public boolean isComponentPinned(ComponentName name) {
        return false;
    }


    // Filter out any activities that the launched uid does not have permission for.
    // To preserve the inputList, optionally will return the original list if any modification has
    // been made.
+24 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.DialogFragment;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
@@ -36,26 +37,33 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment
        implements DialogInterface.OnClickListener {
    private static final String NAME_KEY = "componentName";
    private static final String TITLE_KEY = "title";
    private static final String PINNED_KEY = "pinned";

    // Sync with R.array.resolver_target_actions_* resources
    private static final int APP_INFO_INDEX = 0;
    private static final int TOGGLE_PIN_INDEX = 0;
    private static final int APP_INFO_INDEX = 1;

    public ResolverTargetActionsDialogFragment() {
    }

    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name) {
    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
            boolean pinned) {
        Bundle args = new Bundle();
        args.putCharSequence(TITLE_KEY, title);
        args.putParcelable(NAME_KEY, name);
        args.putBoolean(PINNED_KEY, pinned);
        setArguments(args);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Bundle args = getArguments();
        final int itemRes = args.getBoolean(PINNED_KEY, false)
                ? R.array.resolver_target_actions_unpin
                : R.array.resolver_target_actions_pin;
        return new Builder(getContext())
                .setCancelable(true)
                .setItems(R.array.resolver_target_actions, this)
                .setItems(itemRes, this)
                .setTitle(args.getCharSequence(TITLE_KEY))
                .create();
    }
@@ -65,6 +73,19 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment
        final Bundle args = getArguments();
        ComponentName name = args.getParcelable(NAME_KEY);
        switch (which) {
            case TOGGLE_PIN_INDEX:
                SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext());
                final String key = name.flattenToString();
                boolean currentVal = sp.getBoolean(name.flattenToString(), false);
                if (currentVal) {
                    sp.edit().remove(key).apply();
                } else {
                    sp.edit().putBoolean(key, true).apply();
                }

                // Force the chooser to requery and resort things
                getActivity().recreate();
                break;
            case APP_INFO_INDEX:
                Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        .setData(Uri.fromParts("package", name.getPackageName(), null))
Loading