summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-03-25 19:13:47 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-03-25 19:13:47 +0000
commitea25dfeeea40464a63b2d43f73041c408b949a04 (patch)
tree0b0aa2003059e2ac71f5cfac953a1dddb3f844d8
parentc2d8c7f7a9fad0151e67b467f64b54b4b13d9c9d (diff)
parentd6649924bfd84aebf506f5662a387dc0fb1572f3 (diff)
Merge "Payload selection callback: explicitely encode absent property values." into main
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateTargetIntentInteractor.kt8
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ShareouselUpdate.kt14
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ValueUpdate.kt37
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallback.kt56
-rw-r--r--java/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractor.kt62
-rw-r--r--tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackImplTest.kt143
-rw-r--r--tests/unit/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractorTest.kt40
7 files changed, 223 insertions, 137 deletions
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateTargetIntentInteractor.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateTargetIntentInteractor.kt
index 3ce9aaff..06e28cba 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateTargetIntentInteractor.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/interactor/UpdateTargetIntentInteractor.kt
@@ -26,6 +26,7 @@ import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.Cus
import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.PendingIntentSender
import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.TargetIntentModifier
import com.android.intentresolver.contentpreview.payloadtoggle.domain.intent.toCustomActionModel
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.onValue
import com.android.intentresolver.contentpreview.payloadtoggle.domain.update.SelectionChangeCallback
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel
import javax.inject.Inject
@@ -56,9 +57,10 @@ constructor(
.mapLatest { record -> selectionCallback.onSelectionChanged(record.intent) }
.filterNotNull()
.collect { updates ->
- val actions = updates.customActions ?: emptyList()
- intentRepository.customActions.value =
- actions.map { it.toCustomActionModel(pendingIntentSender) }
+ updates.customActions.onValue { actions ->
+ intentRepository.customActions.value =
+ actions.map { it.toCustomActionModel(pendingIntentSender) }
+ }
chooserParamsUpdateRepository.setUpdates(updates)
}
}
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ShareouselUpdate.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ShareouselUpdate.kt
index 41a34d1a..821e88a5 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ShareouselUpdate.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ShareouselUpdate.kt
@@ -24,11 +24,11 @@ import android.service.chooser.ChooserTarget
/** Sharing session updates provided by the sharing app from the payload change callback */
data class ShareouselUpdate(
// for all properties, null value means no change
- val customActions: List<ChooserAction>? = null,
- val modifyShareAction: ChooserAction? = null,
- val alternateIntents: List<Intent>? = null,
- val callerTargets: List<ChooserTarget>? = null,
- val refinementIntentSender: IntentSender? = null,
- val resultIntentSender: IntentSender? = null,
- val metadataText: CharSequence? = null,
+ val customActions: ValueUpdate<List<ChooserAction>> = ValueUpdate.Absent,
+ val modifyShareAction: ValueUpdate<ChooserAction?> = ValueUpdate.Absent,
+ val alternateIntents: ValueUpdate<List<Intent>> = ValueUpdate.Absent,
+ val callerTargets: ValueUpdate<List<ChooserTarget>> = ValueUpdate.Absent,
+ val refinementIntentSender: ValueUpdate<IntentSender?> = ValueUpdate.Absent,
+ val resultIntentSender: ValueUpdate<IntentSender?> = ValueUpdate.Absent,
+ val metadataText: ValueUpdate<CharSequence?> = ValueUpdate.Absent,
)
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ValueUpdate.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ValueUpdate.kt
new file mode 100644
index 00000000..bad4eebe
--- /dev/null
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/model/ValueUpdate.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.intentresolver.contentpreview.payloadtoggle.domain.model
+
+/** Represents an either updated value or the absence of it */
+sealed interface ValueUpdate<out T> {
+ data class Value<T>(val value: T) : ValueUpdate<T>
+ data object Absent : ValueUpdate<Nothing>
+}
+
+/** Return encapsulated value if this instance represent Value or `default` if Absent */
+fun <T> ValueUpdate<T>.getOrDefault(default: T): T =
+ when (this) {
+ is ValueUpdate.Value -> value
+ is ValueUpdate.Absent -> default
+ }
+
+/** Executes the `block` with encapsulated value if this instance represents Value */
+inline fun <T> ValueUpdate<T>.onValue(block: (T) -> Unit) {
+ if (this is ValueUpdate.Value) {
+ block(value)
+ }
+}
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallback.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallback.kt
index e7644dc5..20af264a 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallback.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallback.kt
@@ -18,6 +18,8 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.update
import android.content.ContentInterface
import android.content.Intent
+import android.content.Intent.EXTRA_ALTERNATE_INTENTS
+import android.content.Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS
import android.content.Intent.EXTRA_CHOOSER_MODIFY_SHARE_ACTION
import android.content.Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER
import android.content.Intent.EXTRA_CHOOSER_RESULT_INTENT_SENDER
@@ -31,6 +33,7 @@ import android.service.chooser.AdditionalContentContract.MethodNames.ON_SELECTIO
import android.service.chooser.ChooserAction
import android.service.chooser.ChooserTarget
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ShareouselUpdate
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
import com.android.intentresolver.inject.AdditionalContent
import com.android.intentresolver.inject.ChooserIntent
import com.android.intentresolver.inject.ChooserServiceFlags
@@ -88,7 +91,10 @@ constructor(
}
?.let { bundle ->
return when (val result = readCallbackResponse(bundle, flags)) {
- is Valid -> result.value
+ is Valid -> {
+ result.warnings.forEach { it.log(TAG) }
+ result.value
+ }
is Invalid -> {
result.errors.forEach { it.log(TAG) }
null
@@ -102,18 +108,40 @@ private fun readCallbackResponse(
flags: ChooserServiceFlags
): ValidationResult<ShareouselUpdate> {
return validateFrom(bundle::get) {
- val customActions = readChooserActions()
- val modifyShareAction = optional(value<ChooserAction>(EXTRA_CHOOSER_MODIFY_SHARE_ACTION))
- val alternateIntents = readAlternateIntents()
- val callerTargets = optional(array<ChooserTarget>(EXTRA_CHOOSER_TARGETS))
+ // An error is treated as an empty collection or null as the presence of a value indicates
+ // an intention to change the old value implying that the old value is obsolete (and should
+ // not be used).
+ val customActions =
+ bundle.readValueUpdate(EXTRA_CHOOSER_CUSTOM_ACTIONS) {
+ readChooserActions() ?: emptyList()
+ }
+ val modifyShareAction =
+ bundle.readValueUpdate(EXTRA_CHOOSER_MODIFY_SHARE_ACTION) { key ->
+ optional(value<ChooserAction>(key))
+ }
+ val alternateIntents =
+ bundle.readValueUpdate(EXTRA_ALTERNATE_INTENTS) {
+ readAlternateIntents() ?: emptyList()
+ }
+ val callerTargets =
+ bundle.readValueUpdate(EXTRA_CHOOSER_TARGETS) { key ->
+ optional(array<ChooserTarget>(key)) ?: emptyList()
+ }
val refinementIntentSender =
- optional(value<IntentSender>(EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER))
- val resultIntentSender = optional(value<IntentSender>(EXTRA_CHOOSER_RESULT_INTENT_SENDER))
+ bundle.readValueUpdate(EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER) { key ->
+ optional(value<IntentSender>(key))
+ }
+ val resultIntentSender =
+ bundle.readValueUpdate(EXTRA_CHOOSER_RESULT_INTENT_SENDER) { key ->
+ optional(value<IntentSender>(key))
+ }
val metadataText =
if (flags.enableSharesheetMetadataExtra()) {
- optional(value<CharSequence>(EXTRA_METADATA_TEXT))
+ bundle.readValueUpdate(EXTRA_METADATA_TEXT) { key ->
+ optional(value<CharSequence>(key))
+ }
} else {
- null
+ ValueUpdate.Absent
}
ShareouselUpdate(
@@ -128,6 +156,16 @@ private fun readCallbackResponse(
}
}
+private inline fun <reified T> Bundle.readValueUpdate(
+ key: String,
+ block: (String) -> T
+): ValueUpdate<T> =
+ if (containsKey(key)) {
+ ValueUpdate.Value(block(key))
+ } else {
+ ValueUpdate.Absent
+ }
+
@Module
@InstallIn(ViewModelComponent::class)
interface SelectionChangeCallbackModule {
diff --git a/java/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractor.kt b/java/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractor.kt
index 4afe46b0..37213403 100644
--- a/java/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractor.kt
+++ b/java/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractor.kt
@@ -17,12 +17,10 @@
package com.android.intentresolver.v2.domain.interactor
import android.content.Intent
-import android.content.IntentSender
-import android.service.chooser.ChooserAction
-import android.service.chooser.ChooserTarget
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.ChooserParamsUpdateRepository
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.TargetIntentRepository
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ShareouselUpdate
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.getOrDefault
import com.android.intentresolver.v2.ui.model.ChooserRequest
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -63,61 +61,27 @@ constructor(
}
private fun updateTargetIntent(targetIntent: Intent) {
- chooserRequestRepository.update { current ->
- current.updatedWith(targetIntent = targetIntent)
- }
+ chooserRequestRepository.update { current -> current.copy(targetIntent = targetIntent) }
}
private fun updateChooserParameters(update: ShareouselUpdate) {
chooserRequestRepository.update { current ->
- current.updatedWith(
- callerChooserTargets = update.callerTargets,
- modifyShareAction = update.modifyShareAction,
- additionalTargets = update.alternateIntents,
- chosenComponentSender = update.resultIntentSender,
- refinementIntentSender = update.refinementIntentSender,
- metadataText = update.metadataText,
+ current.copy(
+ callerChooserTargets =
+ update.callerTargets.getOrDefault(current.callerChooserTargets),
+ modifyShareAction =
+ update.modifyShareAction.getOrDefault(current.modifyShareAction),
+ additionalTargets = update.alternateIntents.getOrDefault(current.additionalTargets),
+ chosenComponentSender =
+ update.resultIntentSender.getOrDefault(current.chosenComponentSender),
+ refinementIntentSender =
+ update.refinementIntentSender.getOrDefault(current.refinementIntentSender),
+ metadataText = update.metadataText.getOrDefault(current.metadataText),
)
}
}
}
-private fun ChooserRequest.updatedWith(
- targetIntent: Intent? = null,
- callerChooserTargets: List<ChooserTarget>? = null,
- modifyShareAction: ChooserAction? = null,
- additionalTargets: List<Intent>? = null,
- chosenComponentSender: IntentSender? = null,
- refinementIntentSender: IntentSender? = null,
- metadataText: CharSequence? = null,
-) =
- ChooserRequest(
- targetIntent ?: this.targetIntent,
- this.targetAction,
- this.isSendActionTarget,
- this.targetType,
- this.launchedFromPackage,
- this.title,
- this.defaultTitleResource,
- this.referrer,
- this.filteredComponentNames,
- callerChooserTargets ?: this.callerChooserTargets,
- this.chooserActions,
- modifyShareAction ?: this.modifyShareAction,
- this.shouldRetainInOnStop,
- additionalTargets ?: this.additionalTargets,
- this.replacementExtras,
- this.initialIntents,
- chosenComponentSender ?: this.chosenComponentSender,
- refinementIntentSender ?: this.refinementIntentSender,
- this.sharedText,
- this.shareTargetFilter,
- this.additionalContentUri,
- this.focusedItemPosition,
- this.contentTypeHint,
- metadataText ?: this.metadataText,
- )
-
@AssistedFactory
@ViewModelScoped
interface ChooserRequestUpdateInteractorFactory {
diff --git a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackImplTest.kt b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackImplTest.kt
index 0dfbfff2..55b32509 100644
--- a/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackImplTest.kt
+++ b/tests/unit/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/update/SelectionChangeCallbackImplTest.kt
@@ -44,6 +44,8 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.intentresolver.any
import com.android.intentresolver.argumentCaptor
import com.android.intentresolver.capture
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate.Absent
import com.android.intentresolver.inject.FakeChooserServiceFlags
import com.android.intentresolver.mock
import com.android.intentresolver.whenever
@@ -51,6 +53,7 @@ import com.google.common.truth.Correspondence
import com.google.common.truth.Correspondence.BinaryPredicate
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
+import java.lang.IllegalArgumentException
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -175,16 +178,16 @@ class SelectionChangeCallbackImplTest {
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
assertWithMessage("Unexpected custom actions")
- .that(result.customActions?.map { it.icon to it.label })
+ .that(result.customActions.getOrThrow().map { it.icon to it.label })
.containsExactly(a1.icon to a1.label, a2.icon to a2.label)
.inOrder()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -213,18 +216,18 @@ class SelectionChangeCallbackImplTest {
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
assertWithMessage("Unexpected modify share action: wrong icon")
- .that(result.modifyShareAction?.icon)
+ .that(result.modifyShareAction.getOrThrow()?.icon)
.isEqualTo(modifyShare.icon)
assertWithMessage("Unexpected modify share action: wrong label")
- .that(result.modifyShareAction?.label)
+ .that(result.modifyShareAction.getOrThrow()?.label)
.isEqualTo(modifyShare.label)
- assertThat(result.customActions).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -248,24 +251,24 @@ class SelectionChangeCallbackImplTest {
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
assertWithMessage("Wrong number of alternate intents")
- .that(result.alternateIntents)
+ .that(result.alternateIntents.getOrThrow())
.hasSize(1)
assertWithMessage("Wrong alternate intent: action")
- .that(result.alternateIntents?.get(0)?.action)
+ .that(result.alternateIntents.getOrThrow()[0].action)
.isEqualTo(alternateIntents[0].action)
assertWithMessage("Wrong alternate intent: categories")
- .that(result.alternateIntents?.get(0)?.categories)
+ .that(result.alternateIntents.getOrThrow()[0].categories)
.containsExactlyElementsIn(alternateIntents[0].categories)
assertWithMessage("Wrong alternate intent: mime type")
- .that(result.alternateIntents?.get(0)?.type)
+ .that(result.alternateIntents.getOrThrow()[0].type)
.isEqualTo(alternateIntents[0].type)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -298,7 +301,7 @@ class SelectionChangeCallbackImplTest {
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
assertWithMessage("Wrong caller targets")
- .that(result.callerTargets)
+ .that(result.callerTargets.getOrThrow())
.comparingElementsUsing(
Correspondence.from(
BinaryPredicate<ChooserTarget?, ChooserTarget> { actual, expected ->
@@ -313,12 +316,12 @@ class SelectionChangeCallbackImplTest {
.containsExactly(t1, t2)
.inOrder()
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -339,13 +342,13 @@ class SelectionChangeCallbackImplTest {
val result = testSubject.onSelectionChanged(targetIntent)
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNotNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender.getOrThrow()).isNotNull()
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -366,13 +369,13 @@ class SelectionChangeCallbackImplTest {
val result = testSubject.onSelectionChanged(targetIntent)
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNotNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender.getOrThrow()).isNotNull()
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -387,13 +390,13 @@ class SelectionChangeCallbackImplTest {
val result = testSubject.onSelectionChanged(targetIntent)
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText).isEqualTo(Absent)
}
@Test
@@ -409,13 +412,13 @@ class SelectionChangeCallbackImplTest {
val result = testSubject.onSelectionChanged(targetIntent)
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isEqualTo(metadataText)
+ assertThat(result.customActions).isEqualTo(Absent)
+ assertThat(result.modifyShareAction).isEqualTo(Absent)
+ assertThat(result.alternateIntents).isEqualTo(Absent)
+ assertThat(result.callerTargets).isEqualTo(Absent)
+ assertThat(result.refinementIntentSender).isEqualTo(Absent)
+ assertThat(result.resultIntentSender).isEqualTo(Absent)
+ assertThat(result.metadataText.getOrThrow()).isEqualTo(metadataText)
}
@Test
@@ -440,14 +443,20 @@ class SelectionChangeCallbackImplTest {
val result = testSubject.onSelectionChanged(targetIntent)
assertWithMessage("Callback result should not be null").that(result).isNotNull()
requireNotNull(result)
- assertThat(result.customActions).isNull()
- assertThat(result.modifyShareAction).isNull()
- assertThat(result.alternateIntents).isNull()
- assertThat(result.callerTargets).isNull()
- assertThat(result.refinementIntentSender).isNull()
- assertThat(result.resultIntentSender).isNull()
- assertThat(result.metadataText).isNull()
+ assertThat(result.customActions.getOrThrow()).isEmpty()
+ assertThat(result.modifyShareAction.getOrThrow()).isNull()
+ assertThat(result.alternateIntents.getOrThrow()).isEmpty()
+ assertThat(result.callerTargets.getOrThrow()).isEmpty()
+ assertThat(result.refinementIntentSender.getOrThrow()).isNull()
+ assertThat(result.resultIntentSender.getOrThrow()).isNull()
+ assertThat(result.metadataText.getOrThrow()).isNull()
}
}
+private fun <T> ValueUpdate<T>.getOrThrow(): T =
+ when (this) {
+ is ValueUpdate.Value -> value
+ else -> throw IllegalArgumentException("Value is expected")
+ }
+
private fun createUri(id: Int) = Uri.parse("content://org.pkg.images/$id.png")
diff --git a/tests/unit/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractorTest.kt b/tests/unit/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractorTest.kt
index d6288e2f..d05a0a91 100644
--- a/tests/unit/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractorTest.kt
+++ b/tests/unit/src/com/android/intentresolver/v2/domain/interactor/ChooserRequestUpdateInteractorTest.kt
@@ -25,6 +25,7 @@ import android.net.Uri
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.ChooserParamsUpdateRepository
import com.android.intentresolver.contentpreview.payloadtoggle.data.repository.TargetIntentRepository
import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ShareouselUpdate
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
import com.android.intentresolver.mock
import com.android.intentresolver.v2.ui.model.ChooserRequest
import com.google.common.truth.Truth.assertThat
@@ -112,7 +113,7 @@ class ChooserRequestUpdateInteractorTest {
val newResultSender = mock<IntentSender>()
chooserParamsUpdateRepository.setUpdates(
ShareouselUpdate(
- resultIntentSender = newResultSender,
+ resultIntentSender = ValueUpdate.Value(newResultSender),
)
)
testScheduler.runCurrent()
@@ -142,7 +143,7 @@ class ChooserRequestUpdateInteractorTest {
val newTargetIntent = Intent(Intent.ACTION_VIEW)
chooserParamsUpdateRepository.setUpdates(
ShareouselUpdate(
- resultIntentSender = newResultSender,
+ resultIntentSender = ValueUpdate.Value(newResultSender),
)
)
testScheduler.runCurrent()
@@ -153,6 +154,41 @@ class ChooserRequestUpdateInteractorTest {
assertThat(requestFlow.value.chosenComponentSender).isSameInstanceAs(newResultSender)
}
+
+ @Test
+ fun testUpdateWithNullValues() =
+ testScope.runTest {
+ val initialRequest =
+ ChooserRequest(
+ targetIntent = targetIntent,
+ targetAction = targetIntent.action,
+ isSendActionTarget = true,
+ targetType = null,
+ launchedFromPackage = "",
+ referrer = null,
+ refinementIntentSender = mock<IntentSender>(),
+ chosenComponentSender = mock<IntentSender>(),
+ )
+ val requestFlow = MutableStateFlow(initialRequest)
+ val testSubject =
+ ChooserRequestUpdateInteractor(
+ targetIntentRepository,
+ chooserParamsUpdateRepository,
+ requestFlow,
+ )
+ backgroundScope.launch { testSubject.launch() }
+
+ chooserParamsUpdateRepository.setUpdates(
+ ShareouselUpdate(
+ resultIntentSender = ValueUpdate.Value(null),
+ refinementIntentSender = ValueUpdate.Value(null),
+ )
+ )
+ testScheduler.runCurrent()
+
+ assertThat(requestFlow.value.chosenComponentSender).isNull()
+ assertThat(requestFlow.value.refinementIntentSender).isNull()
+ }
}
private fun createSomeChooserRequest(targetIntent: Intent) =