diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt index 78231e28803eb..99ed2d99c749b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt @@ -60,6 +60,19 @@ sealed interface NetworkNameModel : Diffable { } } + /** This name has been derived from SubscriptionModel. see [SubscriptionModel] */ + data class SubscriptionDerived(override val name: String) : NetworkNameModel { + override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) { + if (prevVal !is SubscriptionDerived || prevVal.name != name) { + row.logChange(COL_NETWORK_NAME, "SubscriptionDerived($name)") + } + } + + override fun logFull(row: TableRowLogger) { + row.logChange(COL_NETWORK_NAME, "SubscriptionDerived($name)") + } + } + /** * This name has been derived from the sim via * [android.telephony.TelephonyManager.getSimOperatorName]. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt index 16c4027ef6459..27f6df4c26e15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt @@ -34,4 +34,7 @@ data class SubscriptionModel( /** Subscriptions in the same group may be filtered or treated as a single subscription */ val groupUuid: ParcelUuid? = null, + + /** Text representing the name for this connection */ + val carrierName: String, ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt index c1af6df12bd12..a89b1b2db6b31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt @@ -115,9 +115,17 @@ interface MobileConnectionRepository { */ val cdmaRoaming: StateFlow - /** The service provider name for this network connection, or the default name */ + /** The service provider name for this network connection, or the default name. */ val networkName: StateFlow + /** + * The service provider name for this network connection, or the default name. + * + * TODO(b/296600321): De-duplicate this field with [networkName] after determining the data + * provided is identical + */ + val carrierName: StateFlow + /** * True if this type of connection is allowed while airplane mode is on, and false otherwise. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt index 17d20c2978616..c576b822da158 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt @@ -184,7 +184,10 @@ class DemoMobileConnectionRepository( override val cdmaRoaming = MutableStateFlow(false) - override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network")) + override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived(DEMO_CARRIER_NAME)) + + override val carrierName = + MutableStateFlow(NetworkNameModel.SubscriptionDerived(DEMO_CARRIER_NAME)) override val isAllowedDuringAirplaneMode = MutableStateFlow(false) @@ -200,6 +203,7 @@ class DemoMobileConnectionRepository( // This is always true here, because we split out disabled states at the data-source level dataEnabled.value = true networkName.value = NetworkNameModel.IntentDerived(event.name) + carrierName.value = NetworkNameModel.SubscriptionDerived("${event.name} ${event.subId}") _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID @@ -227,6 +231,7 @@ class DemoMobileConnectionRepository( // This is always true here, because we split out disabled states at the data-source level dataEnabled.value = true networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME) + carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME) // TODO(b/276943904): is carrierId a thing with carrier merged networks? _carrierId.value = INVALID_SUBSCRIPTION_ID numberOfLevels.value = event.numberOfLevels @@ -248,6 +253,7 @@ class DemoMobileConnectionRepository( } companion object { + private const val DEMO_CARRIER_NAME = "Demo Carrier" private const val CARRIER_MERGED_NAME = "Carrier Merged Network" } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt index 0e4ceebcc8548..ee13d93e735d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt @@ -92,9 +92,12 @@ constructor( private fun maybeCreateSubscription(subId: Int) { if (!subscriptionInfoCache.containsKey(subId)) { - SubscriptionModel(subscriptionId = subId, isOpportunistic = false).also { - subscriptionInfoCache[subId] = it - } + SubscriptionModel( + subscriptionId = subId, + isOpportunistic = false, + carrierName = DEFAULT_CARRIER_NAME, + ) + .also { subscriptionInfoCache[subId] = it } _subscriptions.value = subscriptionInfoCache.values.toList() } @@ -327,6 +330,7 @@ constructor( private const val TAG = "DemoMobileConnectionsRepo" private const val DEFAULT_SUB_ID = 1 + private const val DEFAULT_CARRIER_NAME = "demo carrier" } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt index 65f4866838371..28be3be289284 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt @@ -108,6 +108,8 @@ class CarrierMergedConnectionRepository( NetworkNameModel.SimDerived(telephonyManager.simOperatorName), ) + override val carrierName: StateFlow = networkName + override val numberOfLevels: StateFlow = wifiRepository.wifiNetwork .map { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt index 8ba7d2197c141..ee11c06ef3f5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt @@ -22,6 +22,7 @@ import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -47,6 +48,7 @@ class FullMobileConnectionRepository( override val subId: Int, startingIsCarrierMerged: Boolean, override val tableLogBuffer: TableLogBuffer, + subscriptionModel: StateFlow, private val defaultNetworkName: NetworkNameModel, private val networkNameSeparator: String, @Application scope: CoroutineScope, @@ -80,6 +82,7 @@ class FullMobileConnectionRepository( mobileRepoFactory.build( subId, tableLogBuffer, + subscriptionModel, defaultNetworkName, networkNameSeparator, ) @@ -287,6 +290,16 @@ class FullMobileConnectionRepository( ) .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.networkName.value) + override val carrierName = + activeRepo + .flatMapLatest { it.carrierName } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + initialValue = activeRepo.value.carrierName.value, + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.carrierName.value) + override val isAllowedDuringAirplaneMode = activeRepo .flatMapLatest { it.isAllowedDuringAirplaneMode } @@ -307,6 +320,7 @@ class FullMobileConnectionRepository( fun build( subId: Int, startingIsCarrierMerged: Boolean, + subscriptionModel: StateFlow, defaultNetworkName: NetworkNameModel, networkNameSeparator: String, ): FullMobileConnectionRepository { @@ -317,6 +331,7 @@ class FullMobileConnectionRepository( subId, startingIsCarrierMerged, mobileLogger, + subscriptionModel, defaultNetworkName, networkNameSeparator, scope, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index aadc975a10dea..1f1ac92b39568 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig import com.android.systemui.statusbar.pipeline.mobile.data.model.toDataConnectionType import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel @@ -80,6 +81,7 @@ import kotlinx.coroutines.flow.stateIn @OptIn(ExperimentalCoroutinesApi::class) class MobileConnectionRepositoryImpl( override val subId: Int, + subscriptionModel: StateFlow, defaultNetworkName: NetworkNameModel, networkNameSeparator: String, private val telephonyManager: TelephonyManager, @@ -281,6 +283,14 @@ class MobileConnectionRepositoryImpl( } .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS) + override val carrierName = + subscriptionModel + .map { + it?.let { model -> NetworkNameModel.SubscriptionDerived(model.carrierName) } + ?: defaultNetworkName + } + .stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName) + /** * There are a few cases where we will need to poll [TelephonyManager] so we can update some * internal state where callbacks aren't provided. Any of those events should be merged into @@ -350,11 +360,13 @@ class MobileConnectionRepositoryImpl( fun build( subId: Int, mobileLogger: TableLogBuffer, + subscriptionModel: StateFlow, defaultNetworkName: NetworkNameModel, networkNameSeparator: String, ): MobileConnectionRepository { return MobileConnectionRepositoryImpl( subId, + subscriptionModel, defaultNetworkName, networkNameSeparator, telephonyManager.createForSubscriptionId(subId), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt index 54948a4a41c83..67b04db644639 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt @@ -319,10 +319,17 @@ constructor( @VisibleForTesting fun getSubIdRepoCache() = subIdRepositoryCache + private fun subscriptionModelForSubId(subId: Int): StateFlow { + return subscriptions + .map { list -> list.firstOrNull { model -> model.subscriptionId == subId } } + .stateIn(scope, SharingStarted.WhileSubscribed(), null) + } + private fun createRepositoryForSubId(subId: Int): FullMobileConnectionRepository { return fullMobileRepoFactory.build( subId, isCarrierMerged(subId), + subscriptionModelForSubId(subId), defaultNetworkName, networkNameSeparator, ) @@ -373,6 +380,7 @@ constructor( subscriptionId = subscriptionId, isOpportunistic = isOpportunistic, groupUuid = groupUuid, + carrierName = carrierName.toString(), ) companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt index 1a138272d67c3..4cfde5bd5622e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt @@ -92,6 +92,22 @@ interface MobileIconInteractor { */ val networkName: StateFlow + /** + * Provider name for this network connection. The name can be one of 3 values: + * 1. The default network name, if one is configured + * 2. A name provided by the [SubscriptionModel] of this network connection + * 3. Or, in the case where the repository sends us the default network name, we check for an + * override in [connectionInfo.operatorAlphaShort], a value that is derived from + * [ServiceState] + * + * TODO(b/296600321): De-duplicate this field with [networkName] after determining the data + * provided is identical + */ + val carrierName: StateFlow + + /** True if there is only one active subscription. */ + val isSingleCarrier: StateFlow + /** True if this line of service is emergency-only */ val isEmergencyOnly: StateFlow @@ -126,6 +142,7 @@ class MobileIconInteractorImpl( defaultSubscriptionHasDataEnabled: StateFlow, override val alwaysShowDataRatIcon: StateFlow, override val alwaysUseCdmaLevel: StateFlow, + override val isSingleCarrier: StateFlow, override val mobileIsDefault: StateFlow, defaultMobileIconMapping: StateFlow>, defaultMobileIconGroup: StateFlow, @@ -171,6 +188,22 @@ class MobileIconInteractorImpl( connectionRepository.networkName.value ) + override val carrierName = + combine(connectionRepository.operatorAlphaShort, connectionRepository.carrierName) { + operatorAlphaShort, + networkName -> + if (networkName is NetworkNameModel.Default && operatorAlphaShort != null) { + operatorAlphaShort + } else { + networkName.name + } + } + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + connectionRepository.carrierName.value.name + ) + /** What the mobile icon would be before carrierId overrides */ private val defaultNetworkType: StateFlow = combine( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt index e90f40c74cc5a..d08808b65399d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt @@ -76,6 +76,9 @@ interface MobileIconsInteractor { /** True if the CDMA level should be preferred over the primary level. */ val alwaysUseCdmaLevel: StateFlow + /** True if there is only one active subscription. */ + val isSingleCarrier: StateFlow + /** The icon mapping from network type to [MobileIconGroup] for the default subscription */ val defaultMobileIconMapping: StateFlow> @@ -252,6 +255,17 @@ constructor( .mapLatest { it.alwaysShowCdmaRssi } .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isSingleCarrier: StateFlow = + mobileConnectionsRepo.subscriptions + .map { it.size == 1 } + .logDiffsForTable( + tableLogger, + columnPrefix = LOGGING_PREFIX, + columnName = "isSingleCarrier", + initialValue = false, + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + /** If there is no mapping in [defaultMobileIconMapping], then use this default icon group */ override val defaultMobileIconGroup: StateFlow = mobileConnectionsRepo.defaultMobileIconGroup.stateIn( @@ -298,6 +312,7 @@ constructor( activeDataConnectionHasDataEnabled, alwaysShowDataRatIcon, alwaysUseCdmaLevel, + isSingleCarrier, mobileIsDefault, defaultMobileIconMapping, defaultMobileIconGroup, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt index 50ee6a31d389e..ff2875355a6ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt @@ -52,12 +52,19 @@ class FakeMobileConnectionRepository( override val cdmaRoaming = MutableStateFlow(false) - override val networkName = - MutableStateFlow(NetworkNameModel.Default("default")) + override val networkName: MutableStateFlow = + MutableStateFlow(NetworkNameModel.Default(DEFAULT_NETWORK_NAME)) + + override val carrierName: MutableStateFlow = + MutableStateFlow(NetworkNameModel.Default(DEFAULT_NETWORK_NAME)) override val isAllowedDuringAirplaneMode = MutableStateFlow(false) fun setDataEnabled(enabled: Boolean) { _dataEnabled.value = enabled } + + companion object { + const val DEFAULT_NETWORK_NAME = "default name" + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt index 3591c17403295..99e4030e11921 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt @@ -75,7 +75,11 @@ class FakeMobileConnectionsRepository( override fun getRepoForSubId(subId: Int): MobileConnectionRepository { return subIdRepos[subId] - ?: FakeMobileConnectionRepository(subId, tableLogBuffer).also { subIdRepos[subId] = it } + ?: FakeMobileConnectionRepository( + subId, + tableLogBuffer, + ) + .also { subIdRepos[subId] = it } } override val defaultDataSubRatConfig = MutableStateFlow(MobileMappings.Config()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt index 5a887ebcee800..d005972043d78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt @@ -243,13 +243,29 @@ class MobileRepositorySwitcherTest : SysuiTestCase() { private val IMMEDIATE = Dispatchers.Main.immediate private const val SUB_1_ID = 1 + private const val SUB_1_NAME = "Carrier $SUB_1_ID" private val SUB_1 = - mock().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) } - private val MODEL_1 = SubscriptionModel(subscriptionId = SUB_1_ID) + mock().also { + whenever(it.subscriptionId).thenReturn(SUB_1_ID) + whenever(it.carrierName).thenReturn(SUB_1_NAME) + } + private val MODEL_1 = + SubscriptionModel( + subscriptionId = SUB_1_ID, + carrierName = SUB_1_NAME, + ) private const val SUB_2_ID = 2 + private const val SUB_2_NAME = "Carrier $SUB_2_ID" private val SUB_2 = - mock().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) } - private val MODEL_2 = SubscriptionModel(subscriptionId = SUB_2_ID) + mock().also { + whenever(it.subscriptionId).thenReturn(SUB_2_ID) + whenever(it.carrierName).thenReturn(SUB_2_NAME) + } + private val MODEL_2 = + SubscriptionModel( + subscriptionId = SUB_2_ID, + carrierName = SUB_2_NAME, + ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index 7573b28c8a7f9..57f97ec66a004 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -38,7 +38,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -140,6 +139,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC launch { conn.carrierNetworkChangeActive.collect {} } launch { conn.isRoaming.collect {} } launch { conn.networkName.collect {} } + launch { conn.carrierName.collect {} } launch { conn.isEmergencyOnly.collect {} } launch { conn.dataConnectionState.collect {} } } @@ -163,6 +163,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC assertThat(conn.isRoaming.value).isEqualTo(model.roaming) assertThat(conn.networkName.value) .isEqualTo(NetworkNameModel.IntentDerived(model.name)) + assertThat(conn.carrierName.value) + .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) // TODO(b/261029387): check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index efaf15235b469..2712b70a97455 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -546,6 +546,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { launch { conn.carrierNetworkChangeActive.collect {} } launch { conn.isRoaming.collect {} } launch { conn.networkName.collect {} } + launch { conn.carrierName.collect {} } launch { conn.isEmergencyOnly.collect {} } launch { conn.dataConnectionState.collect {} } } @@ -571,6 +572,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(conn.isRoaming.value).isEqualTo(model.roaming) assertThat(conn.networkName.value) .isEqualTo(NetworkNameModel.IntentDerived(model.name)) + assertThat(conn.carrierName.value) + .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) // TODO(b/261029387) check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index 3dd2eaff7bce5..9c0cb17700a61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY @@ -43,6 +44,7 @@ import com.google.common.truth.Truth.assertThat import java.io.PrintWriter import java.io.StringWriter import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope @@ -79,28 +81,51 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { private val mobileFactory = mock() private val carrierMergedFactory = mock() + private val subscriptionModel = + MutableStateFlow( + SubscriptionModel( + subscriptionId = SUB_ID, + carrierName = DEFAULT_NAME, + ) + ) + private lateinit var mobileRepo: FakeMobileConnectionRepository private lateinit var carrierMergedRepo: FakeMobileConnectionRepository @Before fun setUp() { - mobileRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer) + mobileRepo = + FakeMobileConnectionRepository( + SUB_ID, + tableLogBuffer, + ) carrierMergedRepo = - FakeMobileConnectionRepository(SUB_ID, tableLogBuffer).apply { - // Mimicks the real carrier merged repository - this.isAllowedDuringAirplaneMode.value = true - } + FakeMobileConnectionRepository( + SUB_ID, + tableLogBuffer, + ) + .apply { + // Mimicks the real carrier merged repository + this.isAllowedDuringAirplaneMode.value = true + } whenever( mobileFactory.build( eq(SUB_ID), any(), - eq(DEFAULT_NAME), + any(), + eq(DEFAULT_NAME_MODEL), eq(SEP), ) ) .thenReturn(mobileRepo) - whenever(carrierMergedFactory.build(eq(SUB_ID), any())).thenReturn(carrierMergedRepo) + whenever( + carrierMergedFactory.build( + eq(SUB_ID), + any(), + ) + ) + .thenReturn(carrierMergedRepo) } @Test @@ -120,7 +145,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { .build( SUB_ID, tableLogBuffer, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, ) } @@ -138,7 +164,11 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo) assertThat(underTest.operatorAlphaShort.value).isEqualTo(nonCarrierMergedName) - verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer) + verify(carrierMergedFactory, never()) + .build( + SUB_ID, + tableLogBuffer, + ) } @Test @@ -348,7 +378,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { factory.build( SUB_ID, startingIsCarrierMerged = false, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, ) @@ -356,7 +387,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { factory.build( SUB_ID, startingIsCarrierMerged = false, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, ) @@ -388,7 +420,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { factory.build( SUB_ID, startingIsCarrierMerged = false, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, ) @@ -397,7 +430,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { factory.build( SUB_ID, startingIsCarrierMerged = true, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, ) @@ -623,7 +657,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { SUB_ID, startingIsCarrierMerged, tableLogBuffer, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, testScope.backgroundScope, mobileFactory, @@ -639,8 +674,9 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { val realRepo = MobileConnectionRepositoryImpl( SUB_ID, - defaultNetworkName = NetworkNameModel.Default("default"), - networkNameSeparator = SEP, + subscriptionModel, + DEFAULT_NAME_MODEL, + SEP, telephonyManager, systemUiCarrierConfig = mock(), fakeBroadcastDispatcher, @@ -654,7 +690,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { mobileFactory.build( eq(SUB_ID), any(), - eq(DEFAULT_NAME), + any(), + eq(DEFAULT_NAME_MODEL), eq(SEP), ) ) @@ -677,7 +714,13 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { testScope.backgroundScope, wifiRepository, ) - whenever(carrierMergedFactory.build(eq(SUB_ID), any())).thenReturn(realRepo) + whenever( + carrierMergedFactory.build( + eq(SUB_ID), + any(), + ) + ) + .thenReturn(realRepo) return realRepo } @@ -690,7 +733,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { private companion object { const val SUB_ID = 42 - private val DEFAULT_NAME = NetworkNameModel.Default("default name") + private val DEFAULT_NAME = "default name" + private val DEFAULT_NAME_MODEL = NetworkNameModel.Default(DEFAULT_NAME) private const val SEP = "-" private const val BUFFER_SEPARATOR = "|" } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index 1ff737bfc137b..e50e5e31a786a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -62,6 +62,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetwork import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig @@ -78,6 +79,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope @@ -109,6 +111,14 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) + private val subscriptionModel: MutableStateFlow = + MutableStateFlow( + SubscriptionModel( + subscriptionId = SUB_1_ID, + carrierName = DEFAULT_NAME, + ) + ) + @Before fun setUp() { MockitoAnnotations.initMocks(this) @@ -119,7 +129,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { underTest = MobileConnectionRepositoryImpl( SUB_1_ID, - DEFAULT_NAME, + subscriptionModel, + DEFAULT_NAME_MODEL, SEP, telephonyManager, systemUiCarrierConfig, @@ -179,6 +190,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { // gsmLevel updates, no change to cdmaLevel strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true) + callback.onSignalStrengthsChanged(strength) assertThat(latest).isEqualTo(2) @@ -637,13 +649,52 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { job.cancel() } + @Test + fun networkNameForSubId_updates() = + testScope.runTest { + var latest: NetworkNameModel? = null + val job = underTest.carrierName.onEach { latest = it }.launchIn(this) + + subscriptionModel.value = + SubscriptionModel( + subscriptionId = SUB_1_ID, + carrierName = DEFAULT_NAME, + ) + + assertThat(latest?.name).isEqualTo(DEFAULT_NAME) + + val updatedName = "Derived Carrier" + subscriptionModel.value = + SubscriptionModel( + subscriptionId = SUB_1_ID, + carrierName = updatedName, + ) + + assertThat(latest?.name).isEqualTo(updatedName) + + job.cancel() + } + + @Test + fun networkNameForSubId_defaultWhenSubscriptionModelNull() = + testScope.runTest { + var latest: NetworkNameModel? = null + val job = underTest.carrierName.onEach { latest = it }.launchIn(this) + + subscriptionModel.value = null + + assertThat(latest?.name).isEqualTo(DEFAULT_NAME) + + job.cancel() + } + @Test fun networkName_default() = testScope.runTest { var latest: NetworkNameModel? = null val job = underTest.networkName.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(DEFAULT_NAME) + assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL) job.cancel() } @@ -701,7 +752,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intentWithoutInfo) - assertThat(latest).isEqualTo(DEFAULT_NAME) + assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL) job.cancel() } @@ -852,8 +903,9 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { companion object { private const val SUB_1_ID = 1 - private val DEFAULT_NAME = NetworkNameModel.Default("default name") - private const val SEP = "-" + private val DEFAULT_NAME = "Fake Mobile Network" + private val DEFAULT_NAME_MODEL = NetworkNameModel.Default(DEFAULT_NAME) + private val SEP = "-" private const val SPN = "testSpn" private const val PLMN = "testPlmn" diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt index 4f15aed00230b..ea60aa74f12bf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository @@ -47,6 +48,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope @@ -97,6 +99,7 @@ class MobileConnectionTelephonySmokeTests : SysuiTestCase() { @Mock private lateinit var telephonyManager: TelephonyManager @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var tableLogger: TableLogBuffer + @Mock private lateinit var subscriptionModel: StateFlow private val mobileMappings = FakeMobileMappingsProxy() private val systemUiCarrierConfig = @@ -113,11 +116,16 @@ class MobileConnectionTelephonySmokeTests : SysuiTestCase() { MockitoAnnotations.initMocks(this) whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID) - connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger) + connectionsRepo = + FakeMobileConnectionsRepository( + mobileMappings, + tableLogger, + ) underTest = MobileConnectionRepositoryImpl( SUB_1_ID, + subscriptionModel, DEFAULT_NAME, SEP, telephonyManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index c8b6f13d69020..fd05cc4956921 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -1190,30 +1190,36 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { companion object { // Subscription 1 private const val SUB_1_ID = 1 + private const val SUB_1_NAME = "Carrier $SUB_1_ID" private val GROUP_1 = ParcelUuid(UUID.randomUUID()) private val SUB_1 = mock().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) whenever(it.groupUuid).thenReturn(GROUP_1) + whenever(it.carrierName).thenReturn(SUB_1_NAME) } private val MODEL_1 = SubscriptionModel( subscriptionId = SUB_1_ID, groupUuid = GROUP_1, + carrierName = SUB_1_NAME, ) // Subscription 2 private const val SUB_2_ID = 2 + private const val SUB_2_NAME = "Carrier $SUB_2_ID" private val GROUP_2 = ParcelUuid(UUID.randomUUID()) private val SUB_2 = mock().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) whenever(it.groupUuid).thenReturn(GROUP_2) + whenever(it.carrierName).thenReturn(SUB_2_NAME) } private val MODEL_2 = SubscriptionModel( subscriptionId = SUB_2_ID, groupUuid = GROUP_2, + carrierName = SUB_2_NAME, ) // Subs 3 and 4 are considered to be in the same group ------------------------------------ @@ -1242,9 +1248,14 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { // Carrier merged subscription private const val SUB_CM_ID = 5 + private const val SUB_CM_NAME = "Carrier $SUB_CM_ID" private val SUB_CM = - mock().also { whenever(it.subscriptionId).thenReturn(SUB_CM_ID) } - private val MODEL_CM = SubscriptionModel(subscriptionId = SUB_CM_ID) + mock().also { + whenever(it.subscriptionId).thenReturn(SUB_CM_ID) + whenever(it.carrierName).thenReturn(SUB_CM_NAME) + } + private val MODEL_CM = + SubscriptionModel(subscriptionId = SUB_CM_ID, carrierName = SUB_CM_NAME) private val WIFI_INFO_CM = mock().apply { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt index 8d1da69d68779..a3df785c5dae8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt @@ -44,6 +44,8 @@ class FakeMobileIconInteractor( override val mobileIsDefault = MutableStateFlow(true) + override val isSingleCarrier = MutableStateFlow(true) + override val networkTypeIconGroup = MutableStateFlow( NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G) @@ -51,6 +53,8 @@ class FakeMobileIconInteractor( override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo mode")) + override val carrierName = MutableStateFlow("demo mode") + private val _isEmergencyOnly = MutableStateFlow(false) override val isEmergencyOnly = _isEmergencyOnly diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt index b2bbcfd3d6efc..82b7ec41d1489 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt @@ -64,6 +64,8 @@ class FakeMobileIconsInteractor( override val mobileIsDefault = MutableStateFlow(false) + override val isSingleCarrier = MutableStateFlow(true) + private val _defaultMobileIconMapping = MutableStateFlow(TEST_MAPPING) override val defaultMobileIconMapping = _defaultMobileIconMapping diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt index 58d3804b71551..e3c59adef529b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType +import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FIVE_G_OVERRIDE import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FOUR_G @@ -40,6 +41,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope @@ -56,6 +58,15 @@ class MobileIconInteractorTest : SysuiTestCase() { private lateinit var underTest: MobileIconInteractor private val mobileMappingsProxy = FakeMobileMappingsProxy() private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock()) + + private val subscriptionModel = + MutableStateFlow( + SubscriptionModel( + subscriptionId = SUB_1_ID, + carrierName = DEFAULT_NAME, + ) + ) + private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock()) private val testDispatcher = UnconfinedTestDispatcher() @@ -432,7 +443,7 @@ class MobileIconInteractorTest : SysuiTestCase() { } @Test - fun networkName_usesOperatorAlphaShotWhenNonNullAndRepoIsDefault() = + fun networkName_usesOperatorAlphaShortWhenNonNullAndRepoIsDefault() = testScope.runTest { var latest: NetworkNameModel? = null val job = underTest.networkName.onEach { latest = it }.launchIn(this) @@ -440,7 +451,7 @@ class MobileIconInteractorTest : SysuiTestCase() { val testOperatorName = "operatorAlphaShort" // Default network name, operator name is non-null, uses the operator name - connectionRepository.networkName.value = DEFAULT_NAME + connectionRepository.networkName.value = DEFAULT_NAME_MODEL connectionRepository.operatorAlphaShort.value = testOperatorName assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName)) @@ -448,10 +459,39 @@ class MobileIconInteractorTest : SysuiTestCase() { // Default network name, operator name is null, uses the default connectionRepository.operatorAlphaShort.value = null + assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL) + + // Derived network name, operator name non-null, uses the derived name + connectionRepository.networkName.value = DERIVED_NAME_MODEL + connectionRepository.operatorAlphaShort.value = testOperatorName + + assertThat(latest).isEqualTo(DERIVED_NAME_MODEL) + + job.cancel() + } + + @Test + fun networkNameForSubId_usesOperatorAlphaShortWhenNonNullAndRepoIsDefault() = + testScope.runTest { + var latest: String? = null + val job = underTest.carrierName.onEach { latest = it }.launchIn(this) + + val testOperatorName = "operatorAlphaShort" + + // Default network name, operator name is non-null, uses the operator name + connectionRepository.carrierName.value = DEFAULT_NAME_MODEL + connectionRepository.operatorAlphaShort.value = testOperatorName + + assertThat(latest).isEqualTo(testOperatorName) + + // Default network name, operator name is null, uses the default + connectionRepository.operatorAlphaShort.value = null + assertThat(latest).isEqualTo(DEFAULT_NAME) // Derived network name, operator name non-null, uses the derived name - connectionRepository.networkName.value = DERIVED_NAME + connectionRepository.carrierName.value = + NetworkNameModel.SubscriptionDerived(DERIVED_NAME) connectionRepository.operatorAlphaShort.value = testOperatorName assertThat(latest).isEqualTo(DERIVED_NAME) @@ -459,6 +499,21 @@ class MobileIconInteractorTest : SysuiTestCase() { job.cancel() } + @Test + fun isSingleCarrier_matchesParent() = + testScope.runTest { + var latest: Boolean? = null + val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this) + + mobileIconsInteractor.isSingleCarrier.value = true + assertThat(latest).isTrue() + + mobileIconsInteractor.isSingleCarrier.value = false + assertThat(latest).isFalse() + + job.cancel() + } + @Test fun isForceHidden_matchesParent() = testScope.runTest { @@ -494,6 +549,7 @@ class MobileIconInteractorTest : SysuiTestCase() { mobileIconsInteractor.activeDataConnectionHasDataEnabled, mobileIconsInteractor.alwaysShowDataRatIcon, mobileIconsInteractor.alwaysUseCdmaLevel, + mobileIconsInteractor.isSingleCarrier, mobileIconsInteractor.mobileIsDefault, mobileIconsInteractor.defaultMobileIconMapping, mobileIconsInteractor.defaultMobileIconGroup, @@ -510,7 +566,9 @@ class MobileIconInteractorTest : SysuiTestCase() { private const val SUB_1_ID = 1 - private val DEFAULT_NAME = NetworkNameModel.Default("test default name") - private val DERIVED_NAME = NetworkNameModel.IntentDerived("test derived name") + private val DEFAULT_NAME = "test default name" + private val DEFAULT_NAME_MODEL = NetworkNameModel.Default(DEFAULT_NAME) + private val DERIVED_NAME = "test derived name" + private val DERIVED_NAME_MODEL = NetworkNameModel.IntentDerived(DERIVED_NAME) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt index 1fb76b048d474..3e6f90931b87a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt @@ -526,6 +526,57 @@ class MobileIconsInteractorTest : SysuiTestCase() { job.cancel() } + @Test + fun isSingleCarrier_zeroSubscriptions_false() = + testScope.runTest { + var latest: Boolean? = true + val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this) + + connectionsRepository.setSubscriptions(emptyList()) + assertThat(latest).isFalse() + + job.cancel() + } + + @Test + fun isSingleCarrier_oneSubscription_true() = + testScope.runTest { + var latest: Boolean? = false + val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this) + + connectionsRepository.setSubscriptions(listOf(SUB_1)) + assertThat(latest).isTrue() + + job.cancel() + } + + @Test + fun isSingleCarrier_twoSubscriptions_false() = + testScope.runTest { + var latest: Boolean? = true + val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this) + + connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2)) + assertThat(latest).isFalse() + + job.cancel() + } + + @Test + fun isSingleCarrier_updates() = + testScope.runTest { + var latest: Boolean? = false + val job = underTest.isSingleCarrier.onEach { latest = it }.launchIn(this) + + connectionsRepository.setSubscriptions(listOf(SUB_1)) + assertThat(latest).isTrue() + + connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2)) + assertThat(latest).isFalse() + + job.cancel() + } + @Test fun mobileIsDefault_mobileFalseAndCarrierMergedFalse_false() = testScope.runTest { @@ -745,6 +796,7 @@ class MobileIconsInteractorTest : SysuiTestCase() { subscriptionId = subscriptionIds.first, isOpportunistic = opportunistic.first, groupUuid = groupUuid, + carrierName = "Carrier ${subscriptionIds.first}" ) val sub2 = @@ -752,6 +804,7 @@ class MobileIconsInteractorTest : SysuiTestCase() { subscriptionId = subscriptionIds.second, isOpportunistic = opportunistic.second, groupUuid = groupUuid, + carrierName = "Carrier ${opportunistic.second}" ) return Pair(sub1, sub2) @@ -760,11 +813,13 @@ class MobileIconsInteractorTest : SysuiTestCase() { companion object { private const val SUB_1_ID = 1 - private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID) + private val SUB_1 = + SubscriptionModel(subscriptionId = SUB_1_ID, carrierName = "Carrier $SUB_1_ID") private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, mock()) private const val SUB_2_ID = 2 - private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID) + private val SUB_2 = + SubscriptionModel(subscriptionId = SUB_2_ID, carrierName = "Carrier $SUB_2_ID") private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, mock()) private const val SUB_3_ID = 3 @@ -773,6 +828,7 @@ class MobileIconsInteractorTest : SysuiTestCase() { subscriptionId = SUB_3_ID, isOpportunistic = true, groupUuid = ParcelUuid(UUID.randomUUID()), + carrierName = "Carrier $SUB_3_ID" ) private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, mock()) @@ -782,6 +838,7 @@ class MobileIconsInteractorTest : SysuiTestCase() { subscriptionId = SUB_4_ID, isOpportunistic = true, groupUuid = ParcelUuid(UUID.randomUUID()), + carrierName = "Carrier $SUB_4_ID" ) private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, mock()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt index f0458fa83d387..e42515e5871de 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt @@ -92,15 +92,31 @@ class MobileIconsViewModelTest : SysuiTestCase() { interactor.filteredSubscriptions.value = listOf( - SubscriptionModel(subscriptionId = 1, isOpportunistic = false), + SubscriptionModel( + subscriptionId = 1, + isOpportunistic = false, + carrierName = "Carrier 1", + ), ) assertThat(latest).isEqualTo(listOf(1)) interactor.filteredSubscriptions.value = listOf( - SubscriptionModel(subscriptionId = 2, isOpportunistic = false), - SubscriptionModel(subscriptionId = 5, isOpportunistic = true), - SubscriptionModel(subscriptionId = 7, isOpportunistic = true), + SubscriptionModel( + subscriptionId = 2, + isOpportunistic = false, + carrierName = "Carrier 2", + ), + SubscriptionModel( + subscriptionId = 5, + isOpportunistic = true, + carrierName = "Carrier 5", + ), + SubscriptionModel( + subscriptionId = 7, + isOpportunistic = true, + carrierName = "Carrier 7", + ), ) assertThat(latest).isEqualTo(listOf(2, 5, 7)) @@ -308,8 +324,23 @@ class MobileIconsViewModelTest : SysuiTestCase() { } companion object { - private val SUB_1 = SubscriptionModel(subscriptionId = 1, isOpportunistic = false) - private val SUB_2 = SubscriptionModel(subscriptionId = 2, isOpportunistic = false) - private val SUB_3 = SubscriptionModel(subscriptionId = 3, isOpportunistic = false) + private val SUB_1 = + SubscriptionModel( + subscriptionId = 1, + isOpportunistic = false, + carrierName = "Carrier 1", + ) + private val SUB_2 = + SubscriptionModel( + subscriptionId = 2, + isOpportunistic = false, + carrierName = "Carrier 2", + ) + private val SUB_3 = + SubscriptionModel( + subscriptionId = 3, + isOpportunistic = false, + carrierName = "Carrier 3", + ) } }