Loading core/java/com/android/internal/app/ChooserActivity.java +57 −26 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.prediction.AppPredictionContext; Loading Loading @@ -131,6 +132,7 @@ import java.util.List; public class ChooserActivity extends ResolverActivity { private static final String TAG = "ChooserActivity"; /** * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself * in onStop when launched in a new task. If this extra is set to true, we do not finish Loading @@ -141,7 +143,6 @@ public class ChooserActivity extends ResolverActivity { private static final boolean DEBUG = false; /** * If {@link #USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS} and this is set to true, * {@link AppPredictionManager} will be queried for direct share targets. Loading Loading @@ -433,18 +434,8 @@ public class ChooserActivity extends ResolverActivity { .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType()) .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { final IntentFilter filter = getTargetIntentFilter(); Bundle extras = new Bundle(); extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter); AppPredictionManager appPredictionManager = getSystemService(AppPredictionManager.class); mAppPredictor = appPredictionManager.createAppPredictionSession( new AppPredictionContext.Builder(this) .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT) .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE) .setExtras(extras) .build()); AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor != null) { mAppPredictorCallback = resultList -> { if (isFinishing() || isDestroyed()) { return; Loading @@ -467,8 +458,10 @@ public class ChooserActivity extends ResolverActivity { appTarget.getPackageName(), appTarget.getClassName()))); } sendShareShortcutInfoList(shareShortcutInfos, driList); sendShortcutManagerShareTargetResultCompleted(); }; mAppPredictor.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback); appPredictor .registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback); } mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null); Loading Loading @@ -872,7 +865,7 @@ public class ChooserActivity extends ResolverActivity { mChooserHandler.removeMessages(LIST_VIEW_UPDATE_MESSAGE); mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT); if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (mAppPredictor != null) { mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback); mAppPredictor.destroy(); } Loading Loading @@ -1205,10 +1198,12 @@ public class ChooserActivity extends ResolverActivity { } private void queryDirectShareTargets(ChooserListAdapter adapter) { if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { mAppPredictor.requestPredictionUpdate(); AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor != null) { appPredictor.requestPredictionUpdate(); return; } // Default to just querying ShortcutManager if AppPredictor not present. final IntentFilter filter = getTargetIntentFilter(); if (filter == null) { return; Loading Loading @@ -1248,11 +1243,15 @@ public class ChooserActivity extends ResolverActivity { } if (resultMessageSent) { sendShortcutManagerShareTargetResultCompleted(); } } private void sendShortcutManagerShareTargetResultCompleted() { final Message msg = Message.obtain(); msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED; mChooserHandler.sendMessage(msg); } } private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) { ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo(); Loading Loading @@ -1309,9 +1308,7 @@ public class ChooserActivity extends ResolverActivity { void updateModelAndChooserCounts(TargetInfo info) { if (info != null) { if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { sendClickToAppPredictor(info); } final ResolveInfo ri = info.getResolveInfo(); Intent targetIntent = getTargetIntent(); if (ri != null && ri.activityInfo != null && targetIntent != null) { Loading @@ -1332,6 +1329,10 @@ public class ChooserActivity extends ResolverActivity { } private void sendClickToAppPredictor(TargetInfo targetInfo) { AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor == null) { return; } if (!(targetInfo instanceof ChooserTargetInfo)) { return; } Loading @@ -1345,8 +1346,9 @@ public class ChooserActivity extends ResolverActivity { if (shortcutId == null) { return; } mAppPredictor.notifyAppTargetEvent( appPredictor.notifyAppTargetEvent( new AppTargetEvent.Builder( // TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId. new AppTarget.Builder(new AppTargetId(shortcutId)) .setTarget(componentName.getPackageName(), getUser()) .setClassName(componentName.getClassName()) Loading @@ -1356,6 +1358,34 @@ public class ChooserActivity extends ResolverActivity { .build()); } @Nullable private AppPredictor getAppPredictor() { if (mAppPredictor == null && getPackageManager().getAppPredictionServicePackageName() != null) { final IntentFilter filter = getTargetIntentFilter(); Bundle extras = new Bundle(); extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter); AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(this) .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE) .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT) .setExtras(extras) .build(); AppPredictionManager appPredictionManager = getSystemService(AppPredictionManager.class); mAppPredictor = appPredictionManager.createAppPredictionSession(appPredictionContext); } return mAppPredictor; } /** * This will return an app predictor if it is enabled for direct share sorting * and if one exists. Otherwise, it returns null. */ @Nullable private AppPredictor getAppPredictorForDirectShareIfEnabled() { return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS ? getAppPredictor() : null; } void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) { if (mRefinementResultReceiver != null) { mRefinementResultReceiver.destroy(); Loading Loading @@ -2014,7 +2044,8 @@ public class ChooserActivity extends ResolverActivity { } } if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS || USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (DEBUG) { Log.d(TAG, "querying direct share targets from ShortcutManager"); } Loading Loading @@ -2242,7 +2273,7 @@ public class ChooserActivity extends ResolverActivity { return CALLER_TARGET_SCORE_BOOST; } if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (getAppPredictorForDirectShareIfEnabled() != null) { return SHORTCUT_TARGET_SCORE_BOOST; } Loading core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.ClipboardManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; Loading @@ -53,7 +54,6 @@ import android.metrics.LogMaker; import android.net.Uri; import android.service.chooser.ChooserTarget; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; Loading @@ -62,10 +62,14 @@ import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.util.Arrays; import java.util.Collection; import java.util.function.Function; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; Loading @@ -75,21 +79,48 @@ import java.util.List; /** * Chooser activity instrumentation tests */ @RunWith(AndroidJUnit4.class) @RunWith(Parameterized.class) public class ChooserActivityTest { private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm; private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM = pm -> { PackageManager mock = Mockito.spy(pm); when(mock.getAppPredictionServicePackageName()).thenReturn(null); return mock; }; @Parameterized.Parameters public static Collection packageManagers() { return Arrays.asList(new Object[][] { {0, "Default PackageManager", DEFAULT_PM}, {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM} }); } private static final int CONTENT_PREVIEW_IMAGE = 1; private static final int CONTENT_PREVIEW_FILE = 2; private static final int CONTENT_PREVIEW_TEXT = 3; private Function<PackageManager, PackageManager> mPackageManagerOverride; private int mTestNum; @Rule public ActivityTestRule<ChooserWrapperActivity> mActivityRule = new ActivityTestRule<>(ChooserWrapperActivity.class, false, false); public ChooserActivityTest( int testNum, String testName, Function<PackageManager, PackageManager> packageManagerOverride) { mPackageManagerOverride = packageManagerOverride; mTestNum = testNum; } @Before public void cleanOverrideData() { sOverrides.reset(); sOverrides.createPackageManager = mPackageManagerOverride; } @Test Loading Loading
core/java/com/android/internal/app/ChooserActivity.java +57 −26 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.prediction.AppPredictionContext; Loading Loading @@ -131,6 +132,7 @@ import java.util.List; public class ChooserActivity extends ResolverActivity { private static final String TAG = "ChooserActivity"; /** * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself * in onStop when launched in a new task. If this extra is set to true, we do not finish Loading @@ -141,7 +143,6 @@ public class ChooserActivity extends ResolverActivity { private static final boolean DEBUG = false; /** * If {@link #USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS} and this is set to true, * {@link AppPredictionManager} will be queried for direct share targets. Loading Loading @@ -433,18 +434,8 @@ public class ChooserActivity extends ResolverActivity { .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType()) .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { final IntentFilter filter = getTargetIntentFilter(); Bundle extras = new Bundle(); extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter); AppPredictionManager appPredictionManager = getSystemService(AppPredictionManager.class); mAppPredictor = appPredictionManager.createAppPredictionSession( new AppPredictionContext.Builder(this) .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT) .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE) .setExtras(extras) .build()); AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor != null) { mAppPredictorCallback = resultList -> { if (isFinishing() || isDestroyed()) { return; Loading @@ -467,8 +458,10 @@ public class ChooserActivity extends ResolverActivity { appTarget.getPackageName(), appTarget.getClassName()))); } sendShareShortcutInfoList(shareShortcutInfos, driList); sendShortcutManagerShareTargetResultCompleted(); }; mAppPredictor.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback); appPredictor .registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback); } mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null); Loading Loading @@ -872,7 +865,7 @@ public class ChooserActivity extends ResolverActivity { mChooserHandler.removeMessages(LIST_VIEW_UPDATE_MESSAGE); mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT); if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (mAppPredictor != null) { mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback); mAppPredictor.destroy(); } Loading Loading @@ -1205,10 +1198,12 @@ public class ChooserActivity extends ResolverActivity { } private void queryDirectShareTargets(ChooserListAdapter adapter) { if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { mAppPredictor.requestPredictionUpdate(); AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor != null) { appPredictor.requestPredictionUpdate(); return; } // Default to just querying ShortcutManager if AppPredictor not present. final IntentFilter filter = getTargetIntentFilter(); if (filter == null) { return; Loading Loading @@ -1248,11 +1243,15 @@ public class ChooserActivity extends ResolverActivity { } if (resultMessageSent) { sendShortcutManagerShareTargetResultCompleted(); } } private void sendShortcutManagerShareTargetResultCompleted() { final Message msg = Message.obtain(); msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED; mChooserHandler.sendMessage(msg); } } private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) { ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo(); Loading Loading @@ -1309,9 +1308,7 @@ public class ChooserActivity extends ResolverActivity { void updateModelAndChooserCounts(TargetInfo info) { if (info != null) { if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { sendClickToAppPredictor(info); } final ResolveInfo ri = info.getResolveInfo(); Intent targetIntent = getTargetIntent(); if (ri != null && ri.activityInfo != null && targetIntent != null) { Loading @@ -1332,6 +1329,10 @@ public class ChooserActivity extends ResolverActivity { } private void sendClickToAppPredictor(TargetInfo targetInfo) { AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor == null) { return; } if (!(targetInfo instanceof ChooserTargetInfo)) { return; } Loading @@ -1345,8 +1346,9 @@ public class ChooserActivity extends ResolverActivity { if (shortcutId == null) { return; } mAppPredictor.notifyAppTargetEvent( appPredictor.notifyAppTargetEvent( new AppTargetEvent.Builder( // TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId. new AppTarget.Builder(new AppTargetId(shortcutId)) .setTarget(componentName.getPackageName(), getUser()) .setClassName(componentName.getClassName()) Loading @@ -1356,6 +1358,34 @@ public class ChooserActivity extends ResolverActivity { .build()); } @Nullable private AppPredictor getAppPredictor() { if (mAppPredictor == null && getPackageManager().getAppPredictionServicePackageName() != null) { final IntentFilter filter = getTargetIntentFilter(); Bundle extras = new Bundle(); extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter); AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(this) .setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE) .setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT) .setExtras(extras) .build(); AppPredictionManager appPredictionManager = getSystemService(AppPredictionManager.class); mAppPredictor = appPredictionManager.createAppPredictionSession(appPredictionContext); } return mAppPredictor; } /** * This will return an app predictor if it is enabled for direct share sorting * and if one exists. Otherwise, it returns null. */ @Nullable private AppPredictor getAppPredictorForDirectShareIfEnabled() { return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS ? getAppPredictor() : null; } void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) { if (mRefinementResultReceiver != null) { mRefinementResultReceiver.destroy(); Loading Loading @@ -2014,7 +2044,8 @@ public class ChooserActivity extends ResolverActivity { } } if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS || USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (DEBUG) { Log.d(TAG, "querying direct share targets from ShortcutManager"); } Loading Loading @@ -2242,7 +2273,7 @@ public class ChooserActivity extends ResolverActivity { return CALLER_TARGET_SCORE_BOOST; } if (USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS) { if (getAppPredictorForDirectShareIfEnabled() != null) { return SHORTCUT_TARGET_SCORE_BOOST; } Loading
core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.ClipboardManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Bitmap; Loading @@ -53,7 +54,6 @@ import android.metrics.LogMaker; import android.net.Uri; import android.service.chooser.ChooserTarget; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; Loading @@ -62,10 +62,14 @@ import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import java.util.Arrays; import java.util.Collection; import java.util.function.Function; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; Loading @@ -75,21 +79,48 @@ import java.util.List; /** * Chooser activity instrumentation tests */ @RunWith(AndroidJUnit4.class) @RunWith(Parameterized.class) public class ChooserActivityTest { private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm; private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM = pm -> { PackageManager mock = Mockito.spy(pm); when(mock.getAppPredictionServicePackageName()).thenReturn(null); return mock; }; @Parameterized.Parameters public static Collection packageManagers() { return Arrays.asList(new Object[][] { {0, "Default PackageManager", DEFAULT_PM}, {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM} }); } private static final int CONTENT_PREVIEW_IMAGE = 1; private static final int CONTENT_PREVIEW_FILE = 2; private static final int CONTENT_PREVIEW_TEXT = 3; private Function<PackageManager, PackageManager> mPackageManagerOverride; private int mTestNum; @Rule public ActivityTestRule<ChooserWrapperActivity> mActivityRule = new ActivityTestRule<>(ChooserWrapperActivity.class, false, false); public ChooserActivityTest( int testNum, String testName, Function<PackageManager, PackageManager> packageManagerOverride) { mPackageManagerOverride = packageManagerOverride; mTestNum = testNum; } @Before public void cleanOverrideData() { sOverrides.reset(); sOverrides.createPackageManager = mPackageManagerOverride; } @Test Loading