diff options
3 files changed, 128 insertions, 2 deletions
diff --git a/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt b/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt index d41d0874..5c785675 100644 --- a/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt +++ b/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt @@ -162,7 +162,13 @@ data class ChooserRequest( * query for matching shortcuts. Specifically, only the [dataTypes][IntentFilter.hasDataType] * are considered for matching share shortcuts currently. */ - val shareTargetFilter: IntentFilter? = null + val shareTargetFilter: IntentFilter? = null, + + /** A URI for additional content */ + val additionalContentUri: Uri? = null, + + /** Focused item index (from target intent's STREAM_EXTRA) */ + val focusedItemPosition: Int = 0, ) { val referrerPackage = referrer?.takeIf { it.scheme == ANDROID_APP_SCHEME }?.authority diff --git a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt index 45e2ea64..167c441f 100644 --- a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt +++ b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt @@ -36,9 +36,11 @@ import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT import android.content.IntentFilter import android.content.IntentSender +import android.net.Uri import android.os.Bundle import android.service.chooser.ChooserAction import android.service.chooser.ChooserTarget +import android.service.chooser.Flags import com.android.intentresolver.ChooserActivity import com.android.intentresolver.R import com.android.intentresolver.util.hasValidIcon @@ -55,6 +57,13 @@ import com.android.intentresolver.v2.validation.validateFrom private const val MAX_CHOOSER_ACTIONS = 5 private const val MAX_INITIAL_INTENTS = 2 +// TODO: replace with the new API constant, Intent#EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI +private const val EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI = + "android.intent.extra.CHOOSER_ADDITIONAL_CONTENT_URI" +// TODO: replace with the new API constant, Intent#EXTRA_CHOOSER_FOCUSED_ITEM_POSITION +private const val EXTRA_CHOOSER_FOCUSED_ITEM_POSITION = + "android.intent.extra.CHOOSER_FOCUSED_ITEM_POSITION" + private fun Intent.hasSendAction() = hasAction(ACTION_SEND, ACTION_SEND_MULTIPLE) internal fun Intent.maybeAddSendActionFlags() = @@ -124,6 +133,16 @@ fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> val referrerFillIn = Intent().putExtra(EXTRA_REFERRER, launch.referrer) + val additionalContentUri: Uri? + val focusedItemPos: Int + if (isSendAction && Flags.chooserPayloadToggling()) { + additionalContentUri = optional(value<Uri>(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI)) + focusedItemPos = optional(value<Int>(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION)) ?: 0 + } else { + additionalContentUri = null + focusedItemPos = 0 + } + ChooserRequest( targetIntent = targetIntent, targetAction = targetIntent.action, @@ -147,7 +166,9 @@ fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> chosenComponentSender = chosenComponentSender, refinementIntentSender = refinementIntentSender, sharedText = sharedText, - shareTargetFilter = targetIntent.toShareTargetFilter() + shareTargetFilter = targetIntent.toShareTargetFilter(), + additionalContentUri = additionalContentUri, + focusedItemPosition = focusedItemPos, ) } } diff --git a/tests/unit/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestTest.kt b/tests/unit/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestTest.kt index 3174c5f6..9ac24c64 100644 --- a/tests/unit/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestTest.kt +++ b/tests/unit/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestTest.kt @@ -19,10 +19,15 @@ import android.content.Intent import android.content.Intent.ACTION_CHOOSER import android.content.Intent.ACTION_SEND import android.content.Intent.ACTION_SEND_MULTIPLE +import android.content.Intent.ACTION_VIEW import android.content.Intent.EXTRA_ALTERNATE_INTENTS import android.content.Intent.EXTRA_INTENT import android.content.Intent.EXTRA_REFERRER import android.net.Uri +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.core.net.toUri import androidx.core.os.bundleOf import com.android.intentresolver.v2.ui.model.ActivityLaunch @@ -30,8 +35,16 @@ import com.android.intentresolver.v2.ui.model.ChooserRequest import com.android.intentresolver.v2.validation.RequiredValueMissing import com.android.intentresolver.v2.validation.ValidationResultSubject.Companion.assertThat import com.google.common.truth.Truth.assertThat +import org.junit.Rule import org.junit.Test +// TODO: replace with the new API constant, Intent#EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI +private const val EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI = + "android.intent.extra.CHOOSER_ADDITIONAL_CONTENT_URI" +// TODO: replace with the new API constant, Intent#EXTRA_CHOOSER_FOCUSED_ITEM_POSITION +private const val EXTRA_CHOOSER_FOCUSED_ITEM_POSITION = + "android.intent.extra.CHOOSER_FOCUSED_ITEM_POSITION" + private fun createLaunch( targetIntent: Intent?, referrer: Uri? = null, @@ -48,6 +61,7 @@ private fun createLaunch( ) class ChooserRequestTest { + @get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() @Test fun missingIntent() { @@ -118,4 +132,89 @@ class ChooserRequestTest { assertThat(value.launchedFromPackage).isEqualTo(launch.fromPackage) assertThat(result).findings().isEmpty() } + + @Test + @RequiresFlagsEnabled(android.service.chooser.Flags.FLAG_CHOOSER_PAYLOAD_TOGGLING) + fun testRequest_actionSendWithAdditionalContentUri() { + val uri = Uri.parse("content://org.pkg/path") + val position = 10 + val launch = + createLaunch(targetIntent = Intent(ACTION_SEND)).apply { + intent.putExtra(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI, uri) + intent.putExtra(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION, position) + } + val result = readChooserRequest(launch) + + assertThat(result).value().isNotNull() + val value: ChooserRequest = result.getOrThrow() + assertThat(value.additionalContentUri).isEqualTo(uri) + assertThat(value.focusedItemPosition).isEqualTo(position) + assertThat(result).findings().isEmpty() + } + + @Test + @RequiresFlagsDisabled(android.service.chooser.Flags.FLAG_CHOOSER_PAYLOAD_TOGGLING) + fun testRequest_actionSendWithAdditionalContentUri_parametersIgnoredWhenFlagDisabled() { + val uri = Uri.parse("content://org.pkg/path") + val position = 10 + val launch = + createLaunch(targetIntent = Intent(ACTION_SEND)).apply { + intent.putExtra(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI, uri) + intent.putExtra(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION, position) + } + val result = readChooserRequest(launch) + + assertThat(result).value().isNotNull() + val value: ChooserRequest = result.getOrThrow() + assertThat(value.additionalContentUri).isNull() + assertThat(value.focusedItemPosition).isEqualTo(0) + assertThat(result).findings().isEmpty() + } + + @Test + @RequiresFlagsEnabled(android.service.chooser.Flags.FLAG_CHOOSER_PAYLOAD_TOGGLING) + fun testRequest_actionSendWithInvalidAdditionalContentUri() { + val launch = + createLaunch(targetIntent = Intent(ACTION_SEND)).apply { + intent.putExtra(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI, "content://org.pkg/path") + intent.putExtra(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION, "1") + } + val result = readChooserRequest(launch) + + assertThat(result).value().isNotNull() + val value: ChooserRequest = result.getOrThrow() + assertThat(value.additionalContentUri).isNull() + assertThat(value.focusedItemPosition).isEqualTo(0) + } + + @Test + @RequiresFlagsEnabled(android.service.chooser.Flags.FLAG_CHOOSER_PAYLOAD_TOGGLING) + fun testRequest_actionSendWithoutAdditionalContentUri() { + val launch = createLaunch(targetIntent = Intent(ACTION_SEND)) + val result = readChooserRequest(launch) + + assertThat(result).value().isNotNull() + val value: ChooserRequest = result.getOrThrow() + assertThat(value.additionalContentUri).isNull() + assertThat(value.focusedItemPosition).isEqualTo(0) + } + + @Test + @RequiresFlagsEnabled(android.service.chooser.Flags.FLAG_CHOOSER_PAYLOAD_TOGGLING) + fun testRequest_actionViewWithAdditionalContentUri() { + val uri = Uri.parse("content://org.pkg/path") + val position = 10 + val launch = + createLaunch(targetIntent = Intent(ACTION_VIEW)).apply { + intent.putExtra(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI, uri) + intent.putExtra(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION, position) + } + val result = readChooserRequest(launch) + + assertThat(result).value().isNotNull() + val value: ChooserRequest = result.getOrThrow() + assertThat(value.additionalContentUri).isNull() + assertThat(value.focusedItemPosition).isEqualTo(0) + assertThat(result).findings().isEmpty() + } } |