summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt8
-rw-r--r--java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt23
-rw-r--r--tests/unit/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestTest.kt99
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()
+ }
}