diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 34e03af4c6663..c235c82de7201 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -218,6 +218,7 @@ public class ChooserActivity extends ResolverActivity implements
public static final int SELECTION_TYPE_STANDARD = 3;
public static final int SELECTION_TYPE_COPY = 4;
public static final int SELECTION_TYPE_NEARBY = 5;
+ public static final int SELECTION_TYPE_EDIT = 6;
private static final int SCROLL_STATUS_IDLE = 0;
private static final int SCROLL_STATUS_SCROLLING_VERTICAL = 1;
@@ -1196,6 +1197,37 @@ public class ChooserActivity extends ResolverActivity implements
return ComponentName.unflattenFromString(nearbyComponent);
}
+ @VisibleForTesting
+ protected @Nullable ComponentName getEditSharingComponent() {
+ String editorPackage = getApplicationContext().getString(R.string.config_systemImageEditor);
+ if (editorPackage == null || TextUtils.isEmpty(editorPackage)) {
+ return null;
+ }
+ return ComponentName.unflattenFromString(editorPackage);
+ }
+
+ @VisibleForTesting
+ protected TargetInfo getEditSharingTarget(Intent originalIntent) {
+ final ComponentName cn = getEditSharingComponent();
+
+ final Intent resolveIntent = new Intent(originalIntent);
+ resolveIntent.setComponent(cn);
+ resolveIntent.setAction(Intent.ACTION_EDIT);
+ final ResolveInfo ri = getPackageManager().resolveActivity(
+ resolveIntent, PackageManager.GET_META_DATA);
+ if (ri == null || ri.activityInfo == null) {
+ Log.e(TAG, "Device-specified image edit component (" + cn
+ + ") not available");
+ return null;
+ }
+
+ final DisplayResolveInfo dri = new DisplayResolveInfo(
+ originalIntent, ri, getString(R.string.screenshot_edit), "", resolveIntent, null);
+ dri.setDisplayIcon(getDrawable(R.drawable.ic_menu_edit));
+ return dri;
+ }
+
+
@VisibleForTesting
protected TargetInfo getNearbySharingTarget(Intent originalIntent) {
final ComponentName cn = getNearbySharingComponent();
@@ -1282,6 +1314,27 @@ public class ChooserActivity extends ResolverActivity implements
return b;
}
+ private @Nullable Button createEditButton(Intent originalIntent) {
+ final TargetInfo ti = getEditSharingTarget(originalIntent);
+ if (ti == null) return null;
+
+ final Button b = createActionButton(
+ ti.getDisplayIcon(this),
+ ti.getDisplayLabel(),
+ (View unused) -> {
+ // Log share completion via edit
+ getChooserActivityLogger().logShareTargetSelected(
+ SELECTION_TYPE_EDIT,
+ "",
+ -1);
+ safelyStartActivity(ti);
+ finish();
+ }
+ );
+ b.setId(R.id.chooser_edit_button);
+ return b;
+ }
+
private void addActionButton(ViewGroup parent, Button b) {
if (b == null) return;
final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(
@@ -1378,6 +1431,7 @@ public class ChooserActivity extends ResolverActivity implements
(ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row);
//TODO: addActionButton(actionRow, createCopyButton());
addActionButton(actionRow, createNearbyButton(targetIntent));
+ addActionButton(actionRow, createEditButton(targetIntent));
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
index 426859e1d5278..c0cc483648fa9 100644
--- a/core/java/com/android/internal/app/ChooserActivityLogger.java
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -118,7 +118,9 @@ public interface ChooserActivityLogger {
@UiEvent(doc = "User selected the copy target.")
SHARESHEET_COPY_TARGET_SELECTED(235),
@UiEvent(doc = "User selected the nearby target.")
- SHARESHEET_NEARBY_TARGET_SELECTED(626);
+ SHARESHEET_NEARBY_TARGET_SELECTED(626),
+ @UiEvent(doc = "User selected the edit target.")
+ SHARESHEET_EDIT_TARGET_SELECTED(627);
private final int mId;
SharesheetTargetSelectedEvent(int id) {
@@ -140,6 +142,8 @@ public interface ChooserActivityLogger {
return SHARESHEET_COPY_TARGET_SELECTED;
case ChooserActivity.SELECTION_TYPE_NEARBY:
return SHARESHEET_NEARBY_TARGET_SELECTED;
+ case ChooserActivity.SELECTION_TYPE_EDIT:
+ return SHARESHEET_EDIT_TARGET_SELECTED;
default:
return INVALID;
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d8da60019130d..1845faacc891e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4605,4 +4605,9 @@
happens that doesn't result in bringing the home task to the front.
This is currently only used on TV. -->
false
+
+
+
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index a12d2a9514609..a4c7293e48b6b 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -206,6 +206,9 @@
+
+
+
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 236f7cb45a814..c72a0cd63b36d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2045,6 +2045,7 @@
+
@@ -3895,6 +3896,7 @@
+
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 787879a6a144c..d9012f649dd36 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -638,6 +638,59 @@ public class ChooserActivityTest {
}
+
+ @Test
+ public void testEditImageLogs() throws Exception {
+ Intent sendIntent = createSendImageIntent(
+ Uri.parse("android.resource://com.android.frameworks.coretests/"
+ + com.android.frameworks.coretests.R.drawable.test320x240));
+
+ sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
+
+ List resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+
+ onView(withId(R.id.chooser_edit_button)).check(matches(isDisplayed()));
+ onView(withId(R.id.chooser_edit_button)).perform(click());
+
+ ChooserActivityLoggerFake logger =
+ (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+ // first one should be SHARESHEET_TRIGGERED uievent
+ assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(0).event.getId(),
+ is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+ // second one should be SHARESHEET_STARTED event
+ assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+ assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+ assertThat(logger.get(1).mimeType, is("image/png"));
+ assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+ assertThat(logger.get(1).appProvidedApp, is(0));
+ assertThat(logger.get(1).appProvidedDirect, is(0));
+ assertThat(logger.get(1).isWorkprofile, is(false));
+ assertThat(logger.get(1).previewType, is(1));
+ // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+ assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(2).event.getId(),
+ is(ChooserActivityLogger
+ .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+ // fourth and fifth are just artifacts of test set-up
+ // sixth one should be ranking atom with SHARESHEET_EDIT_TARGET_SELECTED event
+ assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+ assertThat(logger.get(5).targetType,
+ is(ChooserActivityLogger
+ .SharesheetTargetSelectedEvent.SHARESHEET_EDIT_TARGET_SELECTED.getId()));
+ }
+
+
@Test
public void oneVisibleImagePreview() throws InterruptedException {
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
@@ -2202,6 +2255,19 @@ public class ChooserActivityTest {
return sendIntent;
}
+ private Intent createSendImageIntent(Uri imageThumbnail) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, imageThumbnail);
+ sendIntent.setType("image/png");
+ if (imageThumbnail != null) {
+ ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
+ sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
+ }
+
+ return sendIntent;
+ }
+
private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);