diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java index def11379bdd6e..986614c0963cf 100644 --- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java +++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java @@ -53,6 +53,7 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator private final AppPredictor mAppPredictor; private final Context mContext; private final Map mTargetRanks = new HashMap<>(); + private final Map mTargetScores = new HashMap<>(); private final UserHandle mUser; private final Intent mIntent; private final String mReferrerPackage; @@ -138,6 +139,11 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator // Null value is okay if we have defaulted to the ResolverRankerService. if (msg.what == RANKER_SERVICE_RESULT && msg.obj != null) { final List sortedAppTargets = (List) msg.obj; + if (checkAppTargetRankValid(sortedAppTargets)) { + sortedAppTargets.forEach(target -> mTargetScores.put( + new ComponentName(target.getPackageName(), target.getClassName()), + target.getRank())); + } for (int i = 0; i < sortedAppTargets.size(); i++) { mTargetRanks.put(new ComponentName(sortedAppTargets.get(i).getPackageName(), sortedAppTargets.get(i).getClassName()), i); @@ -147,11 +153,23 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator } } + private boolean checkAppTargetRankValid(List sortedAppTargets) { + for (AppTarget target : sortedAppTargets) { + if (target.getRank() != 0) { + return true; + } + } + return false; + } + @Override float getScore(ComponentName name) { if (mResolverRankerService != null) { return mResolverRankerService.getScore(name); } + if (!mTargetScores.isEmpty()) { + return mTargetScores.get(name); + } Integer rank = mTargetRanks.get(name); if (rank == null) { Log.w(TAG, "Score requested for unknown component."); diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index bdfcda5202817..69a4927c9ab1d 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -207,9 +207,6 @@ public class ChooserListAdapter extends ResolverListAdapter { if (mListViewDataChanged) { if (mAppendDirectShareEnabled) { appendServiceTargetsWithQuota(); - if (mPendingChooserTargetService.isEmpty()) { - fillAllServiceTargets(); - } } super.notifyDataSetChanged(); } @@ -493,6 +490,8 @@ public class ChooserListAdapter extends ResolverListAdapter { pendingChooserTargetServiceConnections) { ComponentName origComponentName = origTarget != null ? origTarget.getResolvedComponentName() : !targets.isEmpty() ? targets.get(0).getComponentName() : null; + Log.i(TAG, + "parkTargetIntoMemory " + origComponentName + ", " + targets.size() + " targets"); mPendingChooserTargetService = pendingChooserTargetServiceConnections.stream() .map(ChooserActivity.ChooserTargetServiceConnection::getComponentName) .filter(componentName -> !componentName.equals(origComponentName)) @@ -532,32 +531,56 @@ public class ChooserListAdapter extends ResolverListAdapter { private void appendServiceTargetsWithQuota() { int maxRankedTargets = mChooserListCommunicator.getMaxRankedTargets(); List topComponentNames = getTopComponentNames(maxRankedTargets); - int appRank = 0; + float totalScore = 0f; for (ComponentName component : topComponentNames) { if (!mPendingChooserTargetService.contains(component) && !mParkingDirectShareTargets.containsKey(component)) { continue; } - appRank++; + totalScore += super.getScore(component); + } + boolean shouldWaitPendingService = false; + for (ComponentName component : topComponentNames) { + if (!mPendingChooserTargetService.contains(component) + && !mParkingDirectShareTargets.containsKey(component)) { + continue; + } + float score = super.getScore(component); + int quota = Math.round(maxRankedTargets * score / totalScore); + if (mPendingChooserTargetService.contains(component) && quota >= 1) { + shouldWaitPendingService = true; + } + if (!mParkingDirectShareTargets.containsKey(component)) { + continue; + } + // Append targets into direct share row as per quota. Pair, Integer> parkingTargetsItem = mParkingDirectShareTargets.get(component); - if (parkingTargetsItem != null && parkingTargetsItem.second == 0) { - List parkingTargets = parkingTargetsItem.first; - int initTargetsQuota = appRank <= maxRankedTargets / 2 ? 2 : 1; - int insertedNum = 0; - while (insertedNum < initTargetsQuota && !parkingTargets.isEmpty()) { - if (!checkDuplicateTarget(parkingTargets.get(0))) { - mServiceTargets.add(mValidServiceTargetsNum, parkingTargets.get(0)); - mValidServiceTargetsNum++; - insertedNum++; - } - parkingTargets.remove(0); - } - mParkingDirectShareTargets.put(component, new Pair<>(parkingTargets, insertedNum)); - if (mShortcutComponents.contains(component)) { - mNumShortcutResults += insertedNum; + List parkingTargets = parkingTargetsItem.first; + int insertedNum = parkingTargetsItem.second; + while (insertedNum < quota && !parkingTargets.isEmpty()) { + if (!checkDuplicateTarget(parkingTargets.get(0))) { + mServiceTargets.add(mValidServiceTargetsNum, parkingTargets.get(0)); + mValidServiceTargetsNum++; + insertedNum++; } + parkingTargets.remove(0); } + Log.i(TAG, " appendServiceTargetsWithQuota component=" + component + + " appendNum=" + (insertedNum - parkingTargetsItem.second)); + if (DEBUG) { + Log.d(TAG, " appendServiceTargetsWithQuota component=" + component + + " score=" + score + + " totalScore=" + totalScore + + " quota=" + quota); + } + if (mShortcutComponents.contains(component)) { + mNumShortcutResults += insertedNum - parkingTargetsItem.second; + } + mParkingDirectShareTargets.put(component, new Pair<>(parkingTargets, insertedNum)); + } + if (!shouldWaitPendingService) { + fillAllServiceTargets(); } } @@ -568,6 +591,7 @@ public class ChooserListAdapter extends ResolverListAdapter { if (mParkingDirectShareTargets.isEmpty()) { return; } + Log.i(TAG, " fillAllServiceTargets"); int maxRankedTargets = mChooserListCommunicator.getMaxRankedTargets(); List topComponentNames = getTopComponentNames(maxRankedTargets); // Append all remaining targets of top recommended components into direct share row. @@ -581,7 +605,8 @@ public class ChooserListAdapter extends ResolverListAdapter { if (mShortcutComponents.contains(component)) { mNumShortcutResults++; } - mServiceTargets.add(target); + mServiceTargets.add(mValidServiceTargetsNum, target); + mValidServiceTargetsNum++; }); mParkingDirectShareTargets.remove(component); } @@ -593,7 +618,8 @@ public class ChooserListAdapter extends ResolverListAdapter { .forEach(targets -> { for (ChooserTargetInfo target : targets) { if (!checkDuplicateTarget(target)) { - mServiceTargets.add(target); + mServiceTargets.add(mValidServiceTargetsNum, target); + mValidServiceTargetsNum++; mNumShortcutResults++; } } diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index cee8a923e198e..62bddb17db5f4 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -153,6 +153,13 @@ public class ResolverListAdapter extends BaseAdapter { return mResolverListController.getScore(target); } + /** + * Returns the app share score of the given {@code componentName}. + */ + public float getScore(ComponentName componentName) { + return mResolverListController.getScore(componentName); + } + /** * Returns the list of top K component names which have highest * {@link #getScore(DisplayResolveInfo)} diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 033ac72dda4ea..2b59907cf86b3 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -377,6 +377,13 @@ public class ResolverListController { return mResolverComparator.getScore(target.getResolvedComponentName()); } + /** + * Returns the app share score of the given {@code componentName}. + */ + public float getScore(ComponentName componentName) { + return mResolverComparator.getScore(componentName); + } + /** * Returns the list of top K component names which have highest * {@link #getScore(DisplayResolveInfo)}