Loading core/java/com/android/internal/app/ChooserActivity.java +33 −10 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ import com.google.android.collect.Lists; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -178,6 +179,20 @@ public class ChooserActivity extends ResolverActivity { private static final boolean USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS = true; private static final boolean USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS = true; public static final int TARGET_TYPE_DEFAULT = 0; public static final int TARGET_TYPE_CHOOSER_TARGET = 1; public static final int TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER = 2; public static final int TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE = 3; @IntDef(flag = false, prefix = { "TARGET_TYPE_" }, value = { TARGET_TYPE_DEFAULT, TARGET_TYPE_CHOOSER_TARGET, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE }) @Retention(RetentionPolicy.SOURCE) public @interface ShareTargetType {} /** * The transition time between placeholders for direct share to a message * indicating that non are available. Loading Loading @@ -218,9 +233,9 @@ public class ChooserActivity extends ResolverActivity { private int mCurrAvailableWidth = 0; /** {@link ChooserActivity#getBaseScore} */ private static final float CALLER_TARGET_SCORE_BOOST = 900.f; public static final float CALLER_TARGET_SCORE_BOOST = 900.f; /** {@link ChooserActivity#getBaseScore} */ private static final float SHORTCUT_TARGET_SCORE_BOOST = 90.f; public static final float SHORTCUT_TARGET_SCORE_BOOST = 90.f; private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment"; // TODO: Update to handle landscape instead of using static value private static final int MAX_RANKED_TARGETS = 4; Loading Loading @@ -443,7 +458,7 @@ public class ChooserActivity extends ResolverActivity { } if (sri.resultTargets != null) { mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets, false); sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET); } unbindService(sri.connection); sri.connection.destroy(); Loading Loading @@ -474,7 +489,7 @@ public class ChooserActivity extends ResolverActivity { final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj; if (resultInfo.resultTargets != null) { mChooserListAdapter.addServiceResults(resultInfo.originalTarget, resultInfo.resultTargets, true); resultInfo.resultTargets, msg.arg1); } break; Loading Loading @@ -1214,7 +1229,7 @@ public class ChooserActivity extends ResolverActivity { mChooserListAdapter = (ChooserListAdapter) adapter; if (mCallerChooserTargets != null && mCallerChooserTargets.length > 0) { mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets), false); TARGET_TYPE_DEFAULT); } mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter); if (listView != null) { Loading Loading @@ -1560,6 +1575,10 @@ public class ChooserActivity extends ResolverActivity { } } // If |appTargets| is not null, results are from AppPredictionService and already sorted. final int shortcutType = (appTargets == null ? TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER : TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE); // Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path // for direct share targets. After ShareSheet is refactored we should use the // ShareShortcutInfos directly. Loading Loading @@ -1587,6 +1606,7 @@ public class ChooserActivity extends ResolverActivity { final Message msg = Message.obtain(); msg.what = ChooserHandler.SHORTCUT_MANAGER_SHARE_TARGET_RESULT; msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null); msg.arg1 = shortcutType; mChooserHandler.sendMessage(msg); resultMessageSent = true; } Loading Loading @@ -2677,7 +2697,7 @@ public class ChooserActivity extends ResolverActivity { * if score is too low. */ public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets, boolean isShortcutResult) { @ShareTargetType int targetType) { if (DEBUG) { Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size() + " targets"); Loading @@ -2687,9 +2707,12 @@ public class ChooserActivity extends ResolverActivity { return; } final float baseScore = getBaseScore(origTarget, isShortcutResult); final float baseScore = getBaseScore(origTarget, targetType); Collections.sort(targets, mBaseTargetComparator); final boolean isShortcutResult = (targetType == TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER || targetType == TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE); final int maxTargets = isShortcutResult ? mMaxShortcutTargetsPerApp : MAX_CHOOSER_TARGETS_PER_APP; float lastScore = 0; Loading Loading @@ -2740,17 +2763,17 @@ public class ChooserActivity extends ResolverActivity { * <li>Legacy direct share targets * </ol> */ private float getBaseScore(DisplayResolveInfo target, boolean isShortcutResult) { public float getBaseScore(DisplayResolveInfo target, @ShareTargetType int targetType) { if (target == null) { return CALLER_TARGET_SCORE_BOOST; } if (isShortcutResult && getAppPredictorForDirectShareIfEnabled() != null) { if (targetType == TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE) { return SHORTCUT_TARGET_SCORE_BOOST; } float score = super.getScore(target); if (isShortcutResult) { if (targetType == TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER) { return score * SHORTCUT_TARGET_SCORE_BOOST; } Loading core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +40 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,12 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.internal.app.ChooserActivity.CALLER_TARGET_SCORE_BOOST; import static com.android.internal.app.ChooserActivity.SHORTCUT_TARGET_SCORE_BOOST; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_CHOOSER_TARGET; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_DEFAULT; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER; import static com.android.internal.app.ChooserWrapperActivity.sOverrides; import static org.hamcrest.CoreMatchers.is; Loading Loading @@ -770,6 +776,37 @@ public class ChooserActivityTest { onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void testGetBaseScore() { final float testBaseScore = 0.89f; Intent sendIntent = createSendTextIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); when(sOverrides.resolverListController.getScore(Mockito.isA( ResolverActivity.DisplayResolveInfo.class))).thenReturn(testBaseScore); final ChooserWrapperActivity activity = mActivityRule .launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); final ResolverActivity.DisplayResolveInfo testDri = activity.createTestDisplayResolveInfo(sendIntent, ResolverDataProvider.createResolveInfo(3, 0), "testLabel", "testInfo", sendIntent); final ChooserActivity.ChooserListAdapter adapter = activity.getAdapter(); assertThat(adapter.getBaseScore(null, 0), is(CALLER_TARGET_SCORE_BOOST)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_DEFAULT), is(testBaseScore)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_CHOOSER_TARGET), is(testBaseScore)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE), is(SHORTCUT_TARGET_SCORE_BOOST)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER), is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST)); } // This test is too long and too slow and should not be taken as an example for future tests. @Test public void testDirectTargetSelectionLogging() throws InterruptedException { Loading Loading @@ -800,7 +837,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading Loading @@ -866,7 +903,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading Loading @@ -927,7 +964,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading Loading
core/java/com/android/internal/app/ChooserActivity.java +33 −10 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ import com.google.android.collect.Lists; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -178,6 +179,20 @@ public class ChooserActivity extends ResolverActivity { private static final boolean USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS = true; private static final boolean USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS = true; public static final int TARGET_TYPE_DEFAULT = 0; public static final int TARGET_TYPE_CHOOSER_TARGET = 1; public static final int TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER = 2; public static final int TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE = 3; @IntDef(flag = false, prefix = { "TARGET_TYPE_" }, value = { TARGET_TYPE_DEFAULT, TARGET_TYPE_CHOOSER_TARGET, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE }) @Retention(RetentionPolicy.SOURCE) public @interface ShareTargetType {} /** * The transition time between placeholders for direct share to a message * indicating that non are available. Loading Loading @@ -218,9 +233,9 @@ public class ChooserActivity extends ResolverActivity { private int mCurrAvailableWidth = 0; /** {@link ChooserActivity#getBaseScore} */ private static final float CALLER_TARGET_SCORE_BOOST = 900.f; public static final float CALLER_TARGET_SCORE_BOOST = 900.f; /** {@link ChooserActivity#getBaseScore} */ private static final float SHORTCUT_TARGET_SCORE_BOOST = 90.f; public static final float SHORTCUT_TARGET_SCORE_BOOST = 90.f; private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment"; // TODO: Update to handle landscape instead of using static value private static final int MAX_RANKED_TARGETS = 4; Loading Loading @@ -443,7 +458,7 @@ public class ChooserActivity extends ResolverActivity { } if (sri.resultTargets != null) { mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets, false); sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET); } unbindService(sri.connection); sri.connection.destroy(); Loading Loading @@ -474,7 +489,7 @@ public class ChooserActivity extends ResolverActivity { final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj; if (resultInfo.resultTargets != null) { mChooserListAdapter.addServiceResults(resultInfo.originalTarget, resultInfo.resultTargets, true); resultInfo.resultTargets, msg.arg1); } break; Loading Loading @@ -1214,7 +1229,7 @@ public class ChooserActivity extends ResolverActivity { mChooserListAdapter = (ChooserListAdapter) adapter; if (mCallerChooserTargets != null && mCallerChooserTargets.length > 0) { mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets), false); TARGET_TYPE_DEFAULT); } mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter); if (listView != null) { Loading Loading @@ -1560,6 +1575,10 @@ public class ChooserActivity extends ResolverActivity { } } // If |appTargets| is not null, results are from AppPredictionService and already sorted. final int shortcutType = (appTargets == null ? TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER : TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE); // Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path // for direct share targets. After ShareSheet is refactored we should use the // ShareShortcutInfos directly. Loading Loading @@ -1587,6 +1606,7 @@ public class ChooserActivity extends ResolverActivity { final Message msg = Message.obtain(); msg.what = ChooserHandler.SHORTCUT_MANAGER_SHARE_TARGET_RESULT; msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null); msg.arg1 = shortcutType; mChooserHandler.sendMessage(msg); resultMessageSent = true; } Loading Loading @@ -2677,7 +2697,7 @@ public class ChooserActivity extends ResolverActivity { * if score is too low. */ public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets, boolean isShortcutResult) { @ShareTargetType int targetType) { if (DEBUG) { Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size() + " targets"); Loading @@ -2687,9 +2707,12 @@ public class ChooserActivity extends ResolverActivity { return; } final float baseScore = getBaseScore(origTarget, isShortcutResult); final float baseScore = getBaseScore(origTarget, targetType); Collections.sort(targets, mBaseTargetComparator); final boolean isShortcutResult = (targetType == TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER || targetType == TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE); final int maxTargets = isShortcutResult ? mMaxShortcutTargetsPerApp : MAX_CHOOSER_TARGETS_PER_APP; float lastScore = 0; Loading Loading @@ -2740,17 +2763,17 @@ public class ChooserActivity extends ResolverActivity { * <li>Legacy direct share targets * </ol> */ private float getBaseScore(DisplayResolveInfo target, boolean isShortcutResult) { public float getBaseScore(DisplayResolveInfo target, @ShareTargetType int targetType) { if (target == null) { return CALLER_TARGET_SCORE_BOOST; } if (isShortcutResult && getAppPredictorForDirectShareIfEnabled() != null) { if (targetType == TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE) { return SHORTCUT_TARGET_SCORE_BOOST; } float score = super.getScore(target); if (isShortcutResult) { if (targetType == TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER) { return score * SHORTCUT_TARGET_SCORE_BOOST; } Loading
core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +40 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,12 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.internal.app.ChooserActivity.CALLER_TARGET_SCORE_BOOST; import static com.android.internal.app.ChooserActivity.SHORTCUT_TARGET_SCORE_BOOST; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_CHOOSER_TARGET; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_DEFAULT; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER; import static com.android.internal.app.ChooserWrapperActivity.sOverrides; import static org.hamcrest.CoreMatchers.is; Loading Loading @@ -770,6 +776,37 @@ public class ChooserActivityTest { onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed())); } @Test public void testGetBaseScore() { final float testBaseScore = 0.89f; Intent sendIntent = createSendTextIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); when(sOverrides.resolverListController.getScore(Mockito.isA( ResolverActivity.DisplayResolveInfo.class))).thenReturn(testBaseScore); final ChooserWrapperActivity activity = mActivityRule .launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); final ResolverActivity.DisplayResolveInfo testDri = activity.createTestDisplayResolveInfo(sendIntent, ResolverDataProvider.createResolveInfo(3, 0), "testLabel", "testInfo", sendIntent); final ChooserActivity.ChooserListAdapter adapter = activity.getAdapter(); assertThat(adapter.getBaseScore(null, 0), is(CALLER_TARGET_SCORE_BOOST)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_DEFAULT), is(testBaseScore)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_CHOOSER_TARGET), is(testBaseScore)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE), is(SHORTCUT_TARGET_SCORE_BOOST)); assertThat(adapter.getBaseScore(testDri, TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER), is(testBaseScore * SHORTCUT_TARGET_SCORE_BOOST)); } // This test is too long and too slow and should not be taken as an example for future tests. @Test public void testDirectTargetSelectionLogging() throws InterruptedException { Loading Loading @@ -800,7 +837,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading Loading @@ -866,7 +903,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading Loading @@ -927,7 +964,7 @@ public class ChooserActivityTest { "testInfo", sendIntent), serviceTargets, false) TARGET_TYPE_CHOOSER_TARGET) ); // Thread.sleep shouldn't be a thing in an integration test but it's // necessary here because of the way the code is structured Loading