From a182e45c6851a8db89e8b0900f0812806ff295d4 Mon Sep 17 00:00:00 2001 From: Adam Powell Date: Mon, 6 Jul 2015 16:57:56 -0700 Subject: [PATCH] Sort and limit ChooserActivity targets from ChooserTargetServices Apply an automated decay factor if apps decide to claim all of their targets are SUPER IMPORTANT. Apply the multiplier from the apps themselves as well as a penalty for apps that come in late - let's see how fast developers get their ChooserTargetServices to start! Also fix a bug with ResolverDrawerLayout where dragging from the title area wouldn't always work properly. Bug 22302285 Change-Id: Ib6eb2b6fb92608790b2267c0f671c9ae59b2907e --- .../android/internal/app/ChooserActivity.java | 84 ++++++++++++++++--- .../internal/app/ResolverActivity.java | 4 + .../internal/app/ResolverComparator.java | 8 ++ .../internal/widget/ResolverDrawerLayout.java | 2 +- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 1b55557e8dd7a..c4f57c7c38bf9 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -59,6 +59,8 @@ import com.android.internal.R; import com.android.internal.logging.MetricsLogger; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; public class ChooserActivity extends ResolverActivity { @@ -97,7 +99,10 @@ public class ChooserActivity extends ResolverActivity { + " Have you considered returning results faster?"); break; } - mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets); + if (sri.resultTargets != null) { + mChooserListAdapter.addServiceResults(sri.originalTarget, + sri.resultTargets); + } unbindService(sri.connection); mServiceConnections.remove(sri.connection); if (mServiceConnections.isEmpty()) { @@ -485,10 +490,13 @@ public class ChooserActivity extends ResolverActivity { private Drawable mDisplayIcon; private final Intent mFillInIntent; private final int mFillInFlags; + private final float mModifiedScore; - public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget) { + public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget, + float modifiedScore) { mSourceInfo = sourceInfo; mChooserTarget = chooserTarget; + mModifiedScore = modifiedScore; if (sourceInfo != null) { final ResolveInfo ri = sourceInfo.getResolveInfo(); if (ri != null) { @@ -520,6 +528,11 @@ public class ChooserActivity extends ResolverActivity { mDisplayIcon = other.mDisplayIcon; mFillInIntent = fillInIntent; mFillInFlags = flags; + mModifiedScore = other.mModifiedScore; + } + + public float getModifiedScore() { + return mModifiedScore; } @Override @@ -632,9 +645,16 @@ public class ChooserActivity extends ResolverActivity { public static final int TARGET_SERVICE = 1; public static final int TARGET_STANDARD = 2; + private static final int MAX_SERVICE_TARGETS = 8; + private final List mServiceTargets = new ArrayList<>(); private final List mCallerTargets = new ArrayList<>(); + private float mLateFee = 1.f; + + private final BaseChooserTargetComparator mBaseTargetComparator + = new BaseChooserTargetComparator(); + public ChooserListAdapter(Context context, List payloadIntents, Intent[] initialIntents, List rList, int launchedFromUid, boolean filterLastUsed) { @@ -703,12 +723,12 @@ public class ChooserActivity extends ResolverActivity { @Override public int getCount() { - return super.getCount() + mServiceTargets.size() + mCallerTargets.size(); + return super.getCount() + getServiceTargetCount() + getCallerTargetCount(); } @Override public int getUnfilteredCount() { - return super.getUnfilteredCount() + mServiceTargets.size() + mCallerTargets.size(); + return super.getUnfilteredCount() + getServiceTargetCount() + getCallerTargetCount(); } public int getCallerTargetCount() { @@ -716,7 +736,7 @@ public class ChooserActivity extends ResolverActivity { } public int getServiceTargetCount() { - return mServiceTargets.size(); + return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS); } public int getStandardTargetCount() { @@ -726,13 +746,13 @@ public class ChooserActivity extends ResolverActivity { public int getPositionTargetType(int position) { int offset = 0; - final int callerTargetCount = mCallerTargets.size(); + final int callerTargetCount = getCallerTargetCount(); if (position < callerTargetCount) { return TARGET_CALLER; } offset += callerTargetCount; - final int serviceTargetCount = mServiceTargets.size(); + final int serviceTargetCount = getServiceTargetCount(); if (position - offset < serviceTargetCount) { return TARGET_SERVICE; } @@ -755,13 +775,13 @@ public class ChooserActivity extends ResolverActivity { public TargetInfo targetInfoForPosition(int position, boolean filtered) { int offset = 0; - final int callerTargetCount = mCallerTargets.size(); + final int callerTargetCount = getCallerTargetCount(); if (position < callerTargetCount) { return mCallerTargets.get(position); } offset += callerTargetCount; - final int serviceTargetCount = mServiceTargets.size(); + final int serviceTargetCount = getServiceTargetCount(); if (position - offset < serviceTargetCount) { return mServiceTargets.get(position - offset); } @@ -774,15 +794,49 @@ public class ChooserActivity extends ResolverActivity { public void addServiceResults(DisplayResolveInfo origTarget, List targets) { if (DEBUG) Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size() + " targets"); + final float parentScore = getScore(origTarget); + Collections.sort(targets, mBaseTargetComparator); + float lastScore = 0; for (int i = 0, N = targets.size(); i < N; i++) { - mServiceTargets.add(new ChooserTargetInfo(origTarget, targets.get(i))); + final ChooserTarget target = targets.get(i); + float targetScore = target.getScore(); + targetScore *= parentScore; + targetScore *= mLateFee; + if (i > 0 && targetScore >= lastScore) { + // Apply a decay so that the top app can't crowd out everything else. + // This incents ChooserTargetServices to define what's truly better. + targetScore = lastScore * 0.95f; + } + insertServiceTarget(new ChooserTargetInfo(origTarget, target, targetScore)); + + if (DEBUG) { + Log.d(TAG, " => " + target.toString() + " score=" + targetScore + + " base=" + target.getScore() + + " lastScore=" + lastScore + + " parentScore=" + parentScore + + " lateFee=" + mLateFee); + } + + lastScore = targetScore; } - // TODO: Maintain sort by ranking scores. + mLateFee *= 0.95f; notifyDataSetChanged(); } + private void insertServiceTarget(ChooserTargetInfo chooserTargetInfo) { + final float newScore = chooserTargetInfo.getModifiedScore(); + for (int i = 0, N = mServiceTargets.size(); i < N; i++) { + final ChooserTargetInfo serviceTarget = mServiceTargets.get(i); + if (newScore > serviceTarget.getModifiedScore()) { + mServiceTargets.add(i, chooserTargetInfo); + return; + } + } + mServiceTargets.add(chooserTargetInfo); + } + private void pruneServiceTargets() { if (DEBUG) Log.d(TAG, "pruneServiceTargets"); for (int i = mServiceTargets.size() - 1; i >= 0; i--) { @@ -795,6 +849,14 @@ public class ChooserActivity extends ResolverActivity { } } + static class BaseChooserTargetComparator implements Comparator { + @Override + public int compare(ChooserTarget lhs, ChooserTarget rhs) { + // Descending order + return (int) Math.signum(lhs.getScore() - rhs.getScore()); + } + } + class ChooserRowAdapter extends BaseAdapter { private ChooserListAdapter mChooserListAdapter; private final LayoutInflater mLayoutInflater; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index e5ff51c4822b2..7bc18f39c8aff 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1142,6 +1142,10 @@ public class ResolverActivity extends Activity { return mFilterLastUsed && mLastChosenPosition >= 0; } + public float getScore(DisplayResolveInfo target) { + return mResolverComparator.getScore(target.getResolvedComponentName()); + } + private void rebuildList() { List currentResolveList = null; diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 585cdf163b8c7..31556e29bc323 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -191,6 +191,14 @@ class ResolverComparator implements Comparator { return mCollator.compare(sa.toString().trim(), sb.toString().trim()); } + public float getScore(ComponentName name) { + final ScoredTarget target = mScoredTargets.get(name); + if (target != null) { + return target.score; + } + return 0; + } + static class ScoredTarget { public final ComponentInfo componentInfo; public float score; diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 1071e12cb6e33..fc9a1a50801ed 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -231,7 +231,7 @@ public class ResolverDrawerLayout extends ViewGroup { mInitialTouchY = mLastTouchY = y; mActivePointerId = ev.getPointerId(0); final boolean hitView = findChildUnder(mInitialTouchX, mInitialTouchY) != null; - handled = (!hitView && mOnDismissedListener != null) || mCollapsibleHeight > 0; + handled = mOnDismissedListener != null || mCollapsibleHeight > 0; mIsDragging = hitView && handled; abortAnimation(); }