diff --git a/app/src/sharedTest/kotlin/com/android/messaging/ui/conversation/messages/ui/message/rendering/BaseConversationMessageRenderingTest.kt b/app/src/sharedTest/kotlin/com/android/messaging/ui/conversation/messages/ui/message/rendering/BaseConversationMessageRenderingTest.kt
index dcc46cc37..d238dc2cf 100644
--- a/app/src/sharedTest/kotlin/com/android/messaging/ui/conversation/messages/ui/message/rendering/BaseConversationMessageRenderingTest.kt
+++ b/app/src/sharedTest/kotlin/com/android/messaging/ui/conversation/messages/ui/message/rendering/BaseConversationMessageRenderingTest.kt
@@ -162,11 +162,13 @@ internal abstract class BaseConversationMessageRenderingTest {
state: MmsDownloadUiModel.State = MmsDownloadUiModel.State.AwaitingManualDownload,
sizeBytes: Long = MMS_SIZE_BYTES,
expiryTimestamp: Long = MMS_EXPIRY_TIMESTAMP,
+ isSecondaryUser: Boolean = false,
): MmsDownloadUiModel {
return MmsDownloadUiModel(
state = state,
sizeBytes = sizeBytes,
expiryTimestamp = expiryTimestamp,
+ isSecondaryUser = isSecondaryUser,
)
}
diff --git a/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/mapper/conversationmessage/ConversationMessageUiModelMapperMmsDownloadTest.kt b/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/mapper/conversationmessage/ConversationMessageUiModelMapperMmsDownloadTest.kt
index 04ce8ad3f..a2b651711 100644
--- a/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/mapper/conversationmessage/ConversationMessageUiModelMapperMmsDownloadTest.kt
+++ b/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/mapper/conversationmessage/ConversationMessageUiModelMapperMmsDownloadTest.kt
@@ -27,6 +27,7 @@ internal class ConversationMessageUiModelMapperMmsDownloadTest :
state = MmsDownloadUiModel.State.AwaitingManualDownload,
sizeBytes = 2_048L,
expiryTimestamp = 1_700_000_000_000L,
+ isSecondaryUser = false,
),
uiModel.mmsDownload,
)
diff --git a/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/ui/message/ResolveConversationMessageSimDisplayNameTest.kt b/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/ui/message/ResolveConversationMessageSimDisplayNameTest.kt
index 6904f3df2..eb4d0355e 100644
--- a/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/ui/message/ResolveConversationMessageSimDisplayNameTest.kt
+++ b/app/src/test/kotlin/com/android/messaging/ui/conversation/messages/ui/message/ResolveConversationMessageSimDisplayNameTest.kt
@@ -152,6 +152,7 @@ class ResolveConversationMessageSimDisplayNameTest {
state = MmsDownloadUiModel.State.AwaitingManualDownload,
sizeBytes = 0L,
expiryTimestamp = 0L,
+ isSecondaryUser = false,
)
}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c9c5c2445..db68736a6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -197,6 +197,10 @@
Downloading…
Message expired or not available
+
+ MMS not available for this user
+
+ Download it from the Owner user
size: %1$s, expiration: %2$s
@@ -494,6 +498,8 @@
Roaming auto-retrieve
Automatically retrieve MMS when roaming
+
+ Only the Owner user can download MMS
Group messaging
Use MMS to send a single message when there are multiple recipients
diff --git a/src/com/android/messaging/datamodel/action/DownloadMmsAction.java b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
index 2852a6121..e866a84a5 100644
--- a/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
+++ b/src/com/android/messaging/datamodel/action/DownloadMmsAction.java
@@ -118,6 +118,11 @@ protected boolean queueAction(final String messageId, final Action processingAct
final MessageData message = BugleDatabaseOperations.readMessage(db, messageId);
if (message != null && message.canDownloadMessage()) {
final Uri notificationUri = message.getSmsMessageUri();
+ if (notificationUri == null) {
+ LogUtil.w(TAG, "DownloadMmsAction: message " + messageId
+ + " has no notification uri; skipping download");
+ return false;
+ }
final String conversationId = message.getConversationId();
final int status = message.getStatus();
diff --git a/src/com/android/messaging/debug/TestDataSeeder.kt b/src/com/android/messaging/debug/TestDataSeeder.kt
index 6a0efc779..a6c9e02a4 100644
--- a/src/com/android/messaging/debug/TestDataSeeder.kt
+++ b/src/com/android/messaging/debug/TestDataSeeder.kt
@@ -957,7 +957,6 @@ private fun insertMmsDownloadMessage(
put(MessageColumns.RECEIVED_TIMESTAMP, timestamp)
put(MessageColumns.SEEN, 1)
put(MessageColumns.READ, 1)
- put(MessageColumns.SMS_MESSAGE_URI, "content://mms/${900_000 + seedIndex}")
put(MessageColumns.SMS_PRIORITY, 0)
put(MessageColumns.SMS_MESSAGE_SIZE, messageSizeBytes)
put(MessageColumns.MMS_TRANSACTION_ID, "seeded-transaction-$seedIndex")
diff --git a/src/com/android/messaging/sms/MmsUtils.java b/src/com/android/messaging/sms/MmsUtils.java
index 5eebec830..71986cd9f 100644
--- a/src/com/android/messaging/sms/MmsUtils.java
+++ b/src/com/android/messaging/sms/MmsUtils.java
@@ -1951,6 +1951,9 @@ public static StatusPlusUri updateSentMmsMessageStatus(final Context context,
}
public static void clearMmsStatus(final Context context, final Uri uri) {
+ if (uri == null) {
+ return;
+ }
// Messaging application can leave invalid values in STATUS field of M-Notification.ind
// messages. Take this opportunity to clear it.
// Downloading status just kept in local db and not reflected into telephony.
diff --git a/src/com/android/messaging/ui/appsettings/subscription/mapper/SubscriptionSettingsUiStateMapper.kt b/src/com/android/messaging/ui/appsettings/subscription/mapper/SubscriptionSettingsUiStateMapper.kt
index e29dce5d3..64695fdbc 100644
--- a/src/com/android/messaging/ui/appsettings/subscription/mapper/SubscriptionSettingsUiStateMapper.kt
+++ b/src/com/android/messaging/ui/appsettings/subscription/mapper/SubscriptionSettingsUiStateMapper.kt
@@ -6,6 +6,7 @@ import com.android.messaging.data.subscriptionsettings.model.PerSubscriptionData
import com.android.messaging.data.subscriptionsettings.model.SubscriptionSettingsData
import com.android.messaging.ui.appsettings.subscription.model.SubscriptionSettingsUiState
import com.android.messaging.ui.appsettings.subscription.model.SubscriptionUiState
+import com.android.messaging.util.OsUtil
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.collections.immutable.ImmutableList
@@ -121,6 +122,7 @@ internal class SubscriptionSettingsUiStateMapperImpl @Inject constructor(
deliveryReportsEnabled = perSub.deliveryReportsEnabled,
isWirelessAlertsSupported = perSub.showCellBroadcast && isCellBroadcastAppEnabled,
isDefaultSmsApp = isDefaultSmsApp,
+ isSecondaryUser = OsUtil.isSecondaryUser(),
)
}
}
diff --git a/src/com/android/messaging/ui/appsettings/subscription/model/SubscriptionUiState.kt b/src/com/android/messaging/ui/appsettings/subscription/model/SubscriptionUiState.kt
index 1d5732dfe..7bea7bf00 100644
--- a/src/com/android/messaging/ui/appsettings/subscription/model/SubscriptionUiState.kt
+++ b/src/com/android/messaging/ui/appsettings/subscription/model/SubscriptionUiState.kt
@@ -17,4 +17,5 @@ internal data class SubscriptionUiState(
val deliveryReportsEnabled: Boolean = false,
val isWirelessAlertsSupported: Boolean = false,
val isDefaultSmsApp: Boolean = false,
+ val isSecondaryUser: Boolean = false,
)
diff --git a/src/com/android/messaging/ui/appsettings/subscription/ui/SubscriptionSettingsScreen.kt b/src/com/android/messaging/ui/appsettings/subscription/ui/SubscriptionSettingsScreen.kt
index cbc78e885..220462bf9 100644
--- a/src/com/android/messaging/ui/appsettings/subscription/ui/SubscriptionSettingsScreen.kt
+++ b/src/com/android/messaging/ui/appsettings/subscription/ui/SubscriptionSettingsScreen.kt
@@ -1,5 +1,6 @@
package com.android.messaging.ui.appsettings.subscription.ui
+import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -169,31 +170,65 @@ private fun LazyListScope.mmsSettingsItems(
)
}
- item(key = "auto_retrieve_mms") {
- SettingsSwitchItem(
- title = stringResource(R.string.auto_retrieve_mms_pref_title),
- summary = stringResource(R.string.auto_retrieve_mms_pref_summary),
- checked = subscriptionSettings.autoRetrieveMms,
- enabled = subscriptionSettings.isDefaultSmsApp,
- onCheckedChange = { enabled ->
- onAction(
- Action.AutoRetrieveMmsChanged(subscriptionSettings.subId, enabled),
- )
- },
- )
- }
+ autoRetrieveMmsItems(
+ subscriptionSettings = subscriptionSettings,
+ onAction = onAction,
+ )
+}
- item(key = "auto_retrieve_mms_roaming") {
+private fun LazyListScope.autoRetrieveMmsItems(
+ subscriptionSettings: SubscriptionUiState,
+ onAction: (Action) -> Unit,
+) {
+ autoRetrieveSwitchItem(
+ key = "auto_retrieve_mms",
+ subscriptionSettings = subscriptionSettings,
+ titleResId = R.string.auto_retrieve_mms_pref_title,
+ summaryResId = R.string.auto_retrieve_mms_pref_summary,
+ checked = subscriptionSettings.autoRetrieveMms,
+ dependencyEnabled = true,
+ onCheckedChange = { enabled ->
+ onAction(Action.AutoRetrieveMmsChanged(subscriptionSettings.subId, enabled))
+ },
+ )
+
+ autoRetrieveSwitchItem(
+ key = "auto_retrieve_mms_roaming",
+ subscriptionSettings = subscriptionSettings,
+ titleResId = R.string.auto_retrieve_mms_when_roaming_pref_title,
+ summaryResId = R.string.auto_retrieve_mms_when_roaming_pref_summary,
+ checked = subscriptionSettings.autoRetrieveMmsWhenRoaming,
+ dependencyEnabled = subscriptionSettings.autoRetrieveMms,
+ onCheckedChange = { enabled ->
+ onAction(Action.AutoRetrieveMmsWhenRoamingChanged(subscriptionSettings.subId, enabled))
+ },
+ )
+}
+
+private fun LazyListScope.autoRetrieveSwitchItem(
+ key: String,
+ subscriptionSettings: SubscriptionUiState,
+ @StringRes titleResId: Int,
+ @StringRes summaryResId: Int,
+ checked: Boolean,
+ dependencyEnabled: Boolean,
+ onCheckedChange: (Boolean) -> Unit,
+) {
+ item(key = key) {
SettingsSwitchItem(
- title = stringResource(R.string.auto_retrieve_mms_when_roaming_pref_title),
- summary = stringResource(R.string.auto_retrieve_mms_when_roaming_pref_summary),
- checked = subscriptionSettings.autoRetrieveMmsWhenRoaming,
- enabled = subscriptionSettings.isDefaultSmsApp && subscriptionSettings.autoRetrieveMms,
- onCheckedChange = { enabled ->
- onAction(
- Action.AutoRetrieveMmsWhenRoamingChanged(subscriptionSettings.subId, enabled),
- )
+ title = stringResource(titleResId),
+ summary = when {
+ subscriptionSettings.isSecondaryUser -> {
+ stringResource(R.string.auto_retrieve_mms_secondary_user_summary)
+ }
+
+ else -> stringResource(summaryResId)
},
+ checked = checked,
+ enabled = subscriptionSettings.isDefaultSmsApp &&
+ dependencyEnabled &&
+ !subscriptionSettings.isSecondaryUser,
+ onCheckedChange = onCheckedChange,
)
}
}
diff --git a/src/com/android/messaging/ui/conversation/messages/mapper/ConversationMessageUiModelMapper.kt b/src/com/android/messaging/ui/conversation/messages/mapper/ConversationMessageUiModelMapper.kt
index a9098cfed..d89c574bd 100644
--- a/src/com/android/messaging/ui/conversation/messages/mapper/ConversationMessageUiModelMapper.kt
+++ b/src/com/android/messaging/ui/conversation/messages/mapper/ConversationMessageUiModelMapper.kt
@@ -10,6 +10,7 @@ import com.android.messaging.ui.conversation.messages.model.message.Conversation
import com.android.messaging.ui.conversation.messages.model.message.MmsDownloadUiModel
import com.android.messaging.util.ContentType
import com.android.messaging.util.LogUtil
+import com.android.messaging.util.OsUtil
import javax.inject.Inject
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@@ -93,6 +94,7 @@ internal class ConversationMessageUiModelMapperImpl @Inject constructor(
state = state,
sizeBytes = data.smsMessageSize.toLong(),
expiryTimestamp = data.mmsExpiry,
+ isSecondaryUser = OsUtil.isSecondaryUser(),
)
}
}
diff --git a/src/com/android/messaging/ui/conversation/messages/model/message/MmsDownloadUiModel.kt b/src/com/android/messaging/ui/conversation/messages/model/message/MmsDownloadUiModel.kt
index 0f7289efa..7bcb13144 100644
--- a/src/com/android/messaging/ui/conversation/messages/model/message/MmsDownloadUiModel.kt
+++ b/src/com/android/messaging/ui/conversation/messages/model/message/MmsDownloadUiModel.kt
@@ -7,6 +7,7 @@ internal data class MmsDownloadUiModel(
val state: State,
val sizeBytes: Long,
val expiryTimestamp: Long,
+ val isSecondaryUser: Boolean,
) {
enum class State {
AwaitingManualDownload,
diff --git a/src/com/android/messaging/ui/conversation/messages/ui/message/ConversationMmsDownloadBody.kt b/src/com/android/messaging/ui/conversation/messages/ui/message/ConversationMmsDownloadBody.kt
index d3257c25f..f074b0eb3 100644
--- a/src/com/android/messaging/ui/conversation/messages/ui/message/ConversationMmsDownloadBody.kt
+++ b/src/com/android/messaging/ui/conversation/messages/ui/message/ConversationMmsDownloadBody.kt
@@ -37,12 +37,26 @@ internal fun ConversationMmsDownloadBody(
isSelected = isSelected,
contentColor = contentColor,
)
+ val isSecondaryUserReferral = isSecondaryUserDownloadReferral(
+ state = download.state,
+ isSecondaryUser = download.isSecondaryUser,
+ )
ConversationMmsDownloadBodyContent(
- titleText = stringResource(id = mmsDownloadTitleResId(state = download.state)),
+ titleText = stringResource(
+ id = mmsDownloadTitleResId(
+ state = download.state,
+ isSecondaryUserReferral = isSecondaryUserReferral,
+ ),
+ ),
infoText = rememberMmsDownloadInfoText(download = download),
statusLineText = rememberMmsDownloadStatusLineText(
- statusText = stringResource(id = mmsDownloadStatusResId(state = download.state)),
+ statusText = stringResource(
+ id = mmsDownloadStatusResId(
+ state = download.state,
+ isSecondaryUserReferral = isSecondaryUserReferral,
+ ),
+ ),
simDisplayName = simDisplayName,
),
contentColor = contentColor,
@@ -50,6 +64,7 @@ internal fun ConversationMmsDownloadBody(
statusColor = mmsDownloadStatusColor(
state = download.state,
canDownloadMessage = canDownloadMessage,
+ isSecondaryUserReferral = isSecondaryUserReferral,
isSelected = isSelected,
contentColor = contentColor,
supportingColor = supportingColor,
@@ -144,28 +159,37 @@ private fun rememberMmsDownloadStatusLineText(
private fun mmsDownloadStatusColor(
state: MmsDownloadUiModel.State,
canDownloadMessage: Boolean,
+ isSecondaryUserReferral: Boolean,
isSelected: Boolean,
contentColor: Color,
supportingColor: Color,
): Color {
+ val canRetryDownload = canDownloadMessage &&
+ (
+ state == MmsDownloadUiModel.State.AwaitingManualDownload ||
+ state == MmsDownloadUiModel.State.DownloadFailed
+ )
+ val isDownloadError = state == MmsDownloadUiModel.State.DownloadFailed ||
+ state == MmsDownloadUiModel.State.ExpiredOrUnavailable
+
return when {
isSelected -> contentColor
- state == MmsDownloadUiModel.State.AwaitingManualDownload && canDownloadMessage -> {
- MaterialTheme.colorScheme.primary
- }
- state == MmsDownloadUiModel.State.DownloadFailed && canDownloadMessage -> {
- MaterialTheme.colorScheme.primary
- }
- state == MmsDownloadUiModel.State.DownloadFailed -> MaterialTheme.colorScheme.error
- state == MmsDownloadUiModel.State.ExpiredOrUnavailable -> {
- MaterialTheme.colorScheme.error
- }
+ isSecondaryUserReferral -> supportingColor
+ canRetryDownload -> MaterialTheme.colorScheme.primary
+ isDownloadError -> MaterialTheme.colorScheme.error
else -> supportingColor
}
}
@StringRes
-private fun mmsDownloadTitleResId(state: MmsDownloadUiModel.State): Int {
+private fun mmsDownloadTitleResId(
+ state: MmsDownloadUiModel.State,
+ isSecondaryUserReferral: Boolean,
+): Int {
+ if (isSecondaryUserReferral) {
+ return R.string.message_title_download_secondary_user
+ }
+
return when (state) {
MmsDownloadUiModel.State.AwaitingManualDownload -> {
R.string.message_title_manual_download
@@ -179,7 +203,14 @@ private fun mmsDownloadTitleResId(state: MmsDownloadUiModel.State): Int {
}
@StringRes
-private fun mmsDownloadStatusResId(state: MmsDownloadUiModel.State): Int {
+private fun mmsDownloadStatusResId(
+ state: MmsDownloadUiModel.State,
+ isSecondaryUserReferral: Boolean,
+): Int {
+ if (isSecondaryUserReferral) {
+ return R.string.message_status_download_secondary_user
+ }
+
return when (state) {
MmsDownloadUiModel.State.AwaitingManualDownload -> {
R.string.message_status_download
@@ -192,6 +223,18 @@ private fun mmsDownloadStatusResId(state: MmsDownloadUiModel.State): Int {
}
}
+private fun isSecondaryUserDownloadReferral(
+ state: MmsDownloadUiModel.State,
+ isSecondaryUser: Boolean,
+): Boolean {
+ return isSecondaryUser && when (state) {
+ MmsDownloadUiModel.State.AwaitingManualDownload -> true
+ MmsDownloadUiModel.State.DownloadFailed -> true
+ MmsDownloadUiModel.State.Downloading -> false
+ MmsDownloadUiModel.State.ExpiredOrUnavailable -> false
+ }
+}
+
private fun buildMmsDownloadInfoText(
context: Context,
download: MmsDownloadUiModel,
diff --git a/src/com/android/messaging/ui/conversation/preview/ConversationPreviewData.kt b/src/com/android/messaging/ui/conversation/preview/ConversationPreviewData.kt
index 9ae96f745..2d2eb92e7 100644
--- a/src/com/android/messaging/ui/conversation/preview/ConversationPreviewData.kt
+++ b/src/com/android/messaging/ui/conversation/preview/ConversationPreviewData.kt
@@ -491,11 +491,13 @@ internal fun previewInlineVCardAttachment(
internal fun previewMmsDownloadUiModel(
state: MmsDownloadUiModel.State = MmsDownloadUiModel.State.AwaitingManualDownload,
+ isSecondaryUser: Boolean = false,
): MmsDownloadUiModel {
return MmsDownloadUiModel(
state = state,
sizeBytes = 2_400_000L,
expiryTimestamp = PREVIEW_NOW_MILLIS + 86_400_000L,
+ isSecondaryUser = isSecondaryUser,
)
}