summaryrefslogtreecommitdiff
path: root/java/src
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 /java/src
parentc2d8c7f7a9fad0151e67b467f64b54b4b13d9c9d (diff)
parentd6649924bfd84aebf506f5662a387dc0fb1572f3 (diff)
Merge "Payload selection callback: explicitely encode absent property values." into main
Diffstat (limited to 'java/src')
-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
5 files changed, 109 insertions, 68 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 {