From 9d501438638ab375fd89a43ab7e366b1f3a4f086 Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Fri, 12 Apr 2019 10:05:29 -0400 Subject: [PATCH] Sharesheet - Prevent duplicate direct share targets Duplicate requests can originate with packageChanged events and when an activity onRestart() is issued. Check for duplicates and do not insert them. Also make sure there is adequate space per row even when display size is at max setting. Bug: 129980100 Test: ChooserActivityTest && visual inspection Change-Id: Ica8afe5d20b8d3ae11be90206b23aaebbb03a2c1 --- .../android/internal/app/ChooserActivity.java | 54 +++++++++++++++---- .../res/drawable/chooser_row_layer_list.xml | 2 +- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index bfdbf4c1ec23c..4d3ccf906ca8f 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -83,6 +83,7 @@ import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; import android.service.chooser.IChooserTargetService; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.util.AttributeSet; import android.util.HashedStringCache; @@ -1518,6 +1519,29 @@ public class ChooserActivity extends ResolverActivity { float getModifiedScore(); ChooserTarget getChooserTarget(); + + /** + * Do not label as 'equals', since this doesn't quite work + * as intended with java 8. + */ + default boolean isSimilar(ChooserTargetInfo other) { + if (other == null) return false; + + ChooserTarget ct1 = getChooserTarget(); + ChooserTarget ct2 = other.getChooserTarget(); + + // If either is null, there is not enough info to make an informed decision + // about equality, so just exit + if (ct1 == null || ct2 == null) return false; + + if (ct1.getComponentName().equals(ct2.getComponentName()) + && TextUtils.equals(getDisplayLabel(), other.getDisplayLabel()) + && TextUtils.equals(getExtendedInfo(), other.getExtendedInfo())) { + return true; + } + + return false; + } } /** @@ -1596,6 +1620,7 @@ public class ChooserActivity extends ResolverActivity { private final DisplayResolveInfo mSourceInfo; private final ResolveInfo mBackupResolveInfo; private final ChooserTarget mChooserTarget; + private final String mDisplayLabel; private Drawable mBadgeIcon = null; private CharSequence mBadgeContentDescription; private Drawable mDisplayIcon; @@ -1633,6 +1658,8 @@ public class ChooserActivity extends ResolverActivity { mFillInIntent = null; mFillInFlags = 0; + + mDisplayLabel = sanitizeDisplayLabel(chooserTarget.getTitle()); } private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) { @@ -1645,6 +1672,14 @@ public class ChooserActivity extends ResolverActivity { mFillInIntent = fillInIntent; mFillInFlags = flags; mModifiedScore = other.mModifiedScore; + + mDisplayLabel = sanitizeDisplayLabel(mChooserTarget.getTitle()); + } + + private String sanitizeDisplayLabel(CharSequence label) { + SpannableStringBuilder sb = new SpannableStringBuilder(label); + sb.clearSpans(); + return sb.toString(); } public boolean isSuspended() { @@ -1783,7 +1818,7 @@ public class ChooserActivity extends ResolverActivity { @Override public CharSequence getDisplayLabel() { - return mChooserTarget.getTitle(); + return mDisplayLabel; } @Override @@ -2196,8 +2231,6 @@ public class ChooserActivity extends ResolverActivity { final float baseScore = getBaseScore(origTarget, isShortcutResult); Collections.sort(targets, mBaseTargetComparator); - - float lastScore = 0; boolean shouldNotify = false; for (int i = 0, N = Math.min(targets.size(), MAX_TARGETS_PER_SERVICE); i < N; i++) { @@ -2272,8 +2305,15 @@ public class ChooserActivity extends ResolverActivity { return false; } - final float newScore = chooserTargetInfo.getModifiedScore(); + // Check for duplicates and abort if found + for (ChooserTargetInfo otherTargetInfo : mServiceTargets) { + if (chooserTargetInfo.isSimilar(otherTargetInfo)) { + return false; + } + } + int currentSize = mServiceTargets.size(); + final float newScore = chooserTargetInfo.getModifiedScore(); for (int i = 0; i < Math.min(currentSize, MAX_SERVICE_TARGETS); i++) { final ChooserTargetInfo serviceTarget = mServiceTargets.get(i); if (serviceTarget == null) { @@ -2360,15 +2400,11 @@ public class ChooserActivity extends ResolverActivity { * @return true if the view width has changed */ public boolean calculateChooserTargetWidth(int width) { - int targetMinWidth = getResources().getDimensionPixelSize( - R.dimen.chooser_target_width); - if (width == 0) { return false; } - int targetWidth = width / getMaxTargetsPerRow(); - int newWidth = Math.max(targetWidth, targetMinWidth); + int newWidth = width / getMaxTargetsPerRow(); if (newWidth != mChooserTargetWidth) { mChooserTargetWidth = newWidth; return true; diff --git a/core/res/res/drawable/chooser_row_layer_list.xml b/core/res/res/drawable/chooser_row_layer_list.xml index 0fb26e13fe57a..080081521ddf2 100644 --- a/core/res/res/drawable/chooser_row_layer_list.xml +++ b/core/res/res/drawable/chooser_row_layer_list.xml @@ -17,7 +17,7 @@ */ --> - +