diff options
20 files changed, 358 insertions, 126 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 30d2295206d8..a8a834f1e8f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -558,8 +558,10 @@ public interface StatusBarIconController { mGroup.addView(view, index, onCreateLayoutParams()); if (mIsInDemoMode) { + Context mobileContext = mMobileContextProvider + .getMobileContextForSub(subId, mContext); mDemoStatusIcons.addModernMobileView( - mContext, + mobileContext, mMobileIconsViewModel.getLogger(), subId); } 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 90c32dc08045..3a11635f75c3 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 @@ -40,6 +40,9 @@ interface MobileConnectionRepository { /** The subscriptionId that this connection represents */ val subId: Int + /** The carrierId for this connection. See [TelephonyManager.getSimCarrierId] */ + val carrierId: StateFlow<Int> + /** * The table log buffer created for this connection. Will have the name "MobileConnectionLog * [subId]" 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 809772eec2f0..6b86432b8171 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 @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo import android.telephony.CellSignalStrength +import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import android.telephony.TelephonyManager import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.logDiffsForTable @@ -25,6 +26,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_ID import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_NETWORK_CHANGE import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CDMA_LEVEL import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY @@ -52,6 +54,17 @@ class DemoMobileConnectionRepository( override val tableLogBuffer: TableLogBuffer, val scope: CoroutineScope, ) : MobileConnectionRepository { + private val _carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID) + override val carrierId = + _carrierId + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_CARRIER_ID, + _carrierId.value, + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value) + private val _isEmergencyOnly = MutableStateFlow(false) override val isEmergencyOnly = _isEmergencyOnly @@ -186,6 +199,8 @@ class DemoMobileConnectionRepository( dataEnabled.value = true networkName.value = NetworkNameModel.IntentDerived(event.name) + _carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID + cdmaRoaming.value = event.roaming _isRoaming.value = event.roaming // TODO(b/261029387): not yet supported @@ -208,6 +223,8 @@ 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) + // TODO(b/276943904): is carrierId a thing with carrier merged networks? + _carrierId.value = INVALID_SUBSCRIPTION_ID numberOfLevels.value = event.numberOfLevels cdmaRoaming.value = false _primaryLevel.value = event.level 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 94d6d0b1db44..a609917351d9 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 @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN +import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID import android.telephony.TelephonyManager import android.util.Log import com.android.systemui.dagger.SysUISingleton @@ -157,6 +158,7 @@ class CarrierMergedConnectionRepository( .stateIn(scope, SharingStarted.WhileSubscribed(), DataConnectionState.Disconnected) override val isRoaming = MutableStateFlow(false).asStateFlow() + override val carrierId = MutableStateFlow(INVALID_SUBSCRIPTION_ID).asStateFlow() override val isEmergencyOnly = MutableStateFlow(false).asStateFlow() override val operatorAlphaShort = MutableStateFlow(null).asStateFlow() override val isInService = MutableStateFlow(true).asStateFlow() 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 b3737ecd1e0b..8869dfe02697 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 @@ -109,6 +109,11 @@ class FullMobileConnectionRepository( .stateIn(scope, SharingStarted.WhileSubscribed(), initial) } + override val carrierId = + activeRepo + .flatMapLatest { it.carrierId } + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.carrierId.value) + override val cdmaRoaming = activeRepo .flatMapLatest { it.cdmaRoaming } @@ -321,13 +326,14 @@ class FullMobileConnectionRepository( } companion object { + const val COL_CARRIER_ID = "carrierId" + const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive" + const val COL_CDMA_LEVEL = "cdmaLevel" const val COL_EMERGENCY = "emergencyOnly" - const val COL_ROAMING = "roaming" - const val COL_OPERATOR = "operatorName" - const val COL_IS_IN_SERVICE = "isInService" const val COL_IS_GSM = "isGsm" - const val COL_CDMA_LEVEL = "cdmaLevel" + const val COL_IS_IN_SERVICE = "isInService" + const val COL_OPERATOR = "operatorName" const val COL_PRIMARY_LEVEL = "primaryLevel" - const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive" + const val COL_ROAMING = "roaming" } } 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 d0c6215a55d8..b475183d98c6 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 @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod -import android.content.Context +import android.content.Intent import android.content.IntentFilter import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN import android.telephony.CellSignalStrengthCdma @@ -31,6 +31,7 @@ import android.telephony.TelephonyManager.ERI_FLASH import android.telephony.TelephonyManager.ERI_ON import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN +import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID import com.android.settingslib.Utils import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.qualifiers.Application @@ -65,6 +66,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.stateIn @@ -75,7 +77,6 @@ import kotlinx.coroutines.flow.stateIn @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @OptIn(ExperimentalCoroutinesApi::class) class MobileConnectionRepositoryImpl( - private val context: Context, override val subId: Int, defaultNetworkName: NetworkNameModel, networkNameSeparator: String, @@ -293,6 +294,23 @@ class MobileConnectionRepositoryImpl( } .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val carrierId = + broadcastDispatcher + .broadcastFlow( + filter = + IntentFilter(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED), + map = { intent, _ -> intent }, + ) + .filter { intent -> + intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, INVALID_SUBSCRIPTION_ID) == subId + } + .map { it.carrierId() } + .onStart { + // Make sure we get the initial carrierId + emit(telephonyManager.simCarrierId) + } + .stateIn(scope, SharingStarted.WhileSubscribed(), telephonyManager.simCarrierId) + override val networkName: StateFlow<NetworkNameModel> = broadcastDispatcher .broadcastFlow( @@ -317,7 +335,6 @@ class MobileConnectionRepositoryImpl( @Inject constructor( private val broadcastDispatcher: BroadcastDispatcher, - private val context: Context, private val telephonyManager: TelephonyManager, private val logger: MobileInputLogger, private val carrierConfigRepository: CarrierConfigRepository, @@ -332,7 +349,6 @@ class MobileConnectionRepositoryImpl( networkNameSeparator: String, ): MobileConnectionRepository { return MobileConnectionRepositoryImpl( - context, subId, defaultNetworkName, networkNameSeparator, @@ -349,6 +365,9 @@ class MobileConnectionRepositoryImpl( } } +private fun Intent.carrierId(): Int = + getIntExtra(TelephonyManager.EXTRA_CARRIER_ID, UNKNOWN_CARRIER_ID) + /** * Wrap every [TelephonyCallback] we care about in a data class so we can accept them in a single * shared flow and then split them back out into other flows. 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 22351f8b2821..1c5ca6bbea21 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 @@ -16,15 +16,22 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor +import android.content.Context import android.telephony.CarrierConfigManager import com.android.settingslib.SignalIcon.MobileIconGroup +import com.android.settingslib.mobile.MobileIconCarrierIdOverrides +import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl import com.android.settingslib.mobile.TelephonyIcons.NOT_DEFAULT_DATA import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.logDiffsForTable import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected 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.repository.MobileConnectionRepository +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel.DefaultIcon +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel.OverriddenIcon import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -35,7 +42,6 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn interface MobileIconInteractor { @@ -76,7 +82,7 @@ interface MobileIconInteractor { val alwaysUseCdmaLevel: StateFlow<Boolean> /** Observable for RAT type (network type) indicator */ - val networkTypeIconGroup: StateFlow<MobileIconGroup> + val networkTypeIconGroup: StateFlow<NetworkTypeIconModel> /** * Provider name for this network connection. The name can be one of 3 values: @@ -123,6 +129,8 @@ class MobileIconInteractorImpl( override val isDefaultConnectionFailed: StateFlow<Boolean>, override val isForceHidden: Flow<Boolean>, connectionRepository: MobileConnectionRepository, + private val context: Context, + val carrierIdOverrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl() ) : MobileIconInteractor { override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer @@ -139,6 +147,15 @@ class MobileIconInteractorImpl( connectionRepository.subId == defaultDataSubId.value ) + // True if there exists _any_ icon override for this carrierId. Note that overrides can include + // any or none of the icon groups defined in MobileMappings, so we still need to check on a + // per-network-type basis whether or not the given icon group is overridden + private val carrierIdIconOverrideExists = + connectionRepository.carrierId + .map { carrierIdOverrides.carrierIdEntryExists(it) } + .distinctUntilChanged() + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled override val networkName = @@ -157,8 +174,8 @@ class MobileIconInteractorImpl( connectionRepository.networkName.value ) - /** Observable for the current RAT indicator icon ([MobileIconGroup]) */ - override val networkTypeIconGroup: StateFlow<MobileIconGroup> = + /** What the mobile icon would be before carrierId overrides */ + private val defaultNetworkType: StateFlow<MobileIconGroup> = combine( connectionRepository.resolvedNetworkType, defaultMobileIconMapping, @@ -172,21 +189,47 @@ class MobileIconInteractorImpl( when (resolvedNetworkType) { is ResolvedNetworkType.CarrierMergedNetworkType -> resolvedNetworkType.iconGroupOverride - else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup + else -> { + mapping[resolvedNetworkType.lookupKey] ?: defaultGroup + } } } - .distinctUntilChanged() - .onEach { - // Doesn't use [logDiffsForTable] because [MobileIconGroup] can't implement the - // [Diffable] interface. - tableLogBuffer.logChange( - prefix = "", - columnName = "networkTypeIcon", - value = it.name - ) - } .stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value) + override val networkTypeIconGroup = + combine( + defaultNetworkType, + carrierIdIconOverrideExists, + ) { networkType, overrideExists -> + // DefaultIcon comes out of the icongroup lookup, we check for overrides here + if (overrideExists) { + val iconOverride = + carrierIdOverrides.getOverrideFor( + connectionRepository.carrierId.value, + networkType.name, + context.resources, + ) + if (iconOverride > 0) { + OverriddenIcon(networkType, iconOverride) + } else { + DefaultIcon(networkType) + } + } else { + DefaultIcon(networkType) + } + } + .distinctUntilChanged() + .logDiffsForTable( + tableLogBuffer = tableLogBuffer, + columnPrefix = "", + initialValue = DefaultIcon(defaultMobileIconGroup.value), + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + DefaultIcon(defaultMobileIconGroup.value), + ) + override val isEmergencyOnly = connectionRepository.isEmergencyOnly override val isRoaming: StateFlow<Boolean> = 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 6c8310ac3d29..7ec9ed8ccf2d 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 @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor +import android.content.Context import android.telephony.CarrierConfigManager import android.telephony.SubscriptionManager import com.android.settingslib.SignalIcon.MobileIconGroup @@ -112,6 +113,7 @@ constructor( connectivityRepository: ConnectivityRepository, userSetupRepo: UserSetupRepository, @Application private val scope: CoroutineScope, + private val context: Context, ) : MobileIconsInteractor { override val mobileIsDefault = mobileConnectionsRepo.mobileIsDefault @@ -286,6 +288,7 @@ constructor( isDefaultConnectionFailed, isForceHidden, mobileConnectionsRepo.getRepoForSubId(subId), + context, ) companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/model/NetworkTypeIconModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/model/NetworkTypeIconModel.kt new file mode 100644 index 000000000000..6ea5f90ddc71 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/model/NetworkTypeIconModel.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 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.systemui.statusbar.pipeline.mobile.domain.model + +import com.android.settingslib.SignalIcon.MobileIconGroup +import com.android.systemui.log.table.Diffable +import com.android.systemui.log.table.TableRowLogger + +/** + * A data wrapper class for [MobileIconGroup]. One lingering nuance of this pipeline is its + * dependency on MobileMappings for its lookup from NetworkType -> NetworkTypeIcon. And because + * MobileMappings is a static map of (netType, icon) that knows nothing of `carrierId`, we need the + * concept of a "default" or "overridden" icon type. + * + * Until we can remove that dependency on MobileMappings, we should just allow for the composition + * of overriding an icon id using the lookup defined in [MobileIconCarrierIdOverrides]. By using the + * [overrideIcon] method defined below, we can create any arbitrarily overridden network type icon. + */ +sealed interface NetworkTypeIconModel : Diffable<NetworkTypeIconModel> { + val contentDescription: Int + val iconId: Int + val name: String + + data class DefaultIcon( + val iconGroup: MobileIconGroup, + ) : NetworkTypeIconModel { + override val contentDescription = iconGroup.dataContentDescription + override val iconId = iconGroup.dataType + override val name = iconGroup.name + + override fun logDiffs(prevVal: NetworkTypeIconModel, row: TableRowLogger) { + if (prevVal !is DefaultIcon || prevVal.name != name) { + row.logChange(COL_NETWORK_ICON, name) + } + } + } + + data class OverriddenIcon( + val iconGroup: MobileIconGroup, + override val iconId: Int, + ) : NetworkTypeIconModel { + override val contentDescription = iconGroup.dataContentDescription + override val name = iconGroup.name + + override fun logDiffs(prevVal: NetworkTypeIconModel, row: TableRowLogger) { + if (prevVal !is OverriddenIcon || prevVal.name != name || prevVal.iconId != iconId) { + row.logChange(COL_NETWORK_ICON, "Ovrd($name)") + } + } + } + + companion object { + const val COL_NETWORK_ICON = "networkTypeIcon" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt index 62bc27f9dd4e..50877eb4c72c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt @@ -167,12 +167,12 @@ constructor( showNetworkTypeIcon, ) { networkTypeIconGroup, shouldShow -> val desc = - if (networkTypeIconGroup.dataContentDescription != 0) - ContentDescription.Resource(networkTypeIconGroup.dataContentDescription) + if (networkTypeIconGroup.contentDescription != 0) + ContentDescription.Resource(networkTypeIconGroup.contentDescription) else null val icon = - if (networkTypeIconGroup.dataType != 0) - Icon.Resource(networkTypeIconGroup.dataType, desc) + if (networkTypeIconGroup.iconId != 0) + Icon.Resource(networkTypeIconGroup.iconId, desc) else null return@combine when { !shouldShow -> null 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 44fbd5b99894..6306a36d9730 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 @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository +import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel @@ -29,6 +30,7 @@ class FakeMobileConnectionRepository( override val subId: Int, override val tableLogBuffer: TableLogBuffer, ) : MobileConnectionRepository { + override val carrierId = MutableStateFlow(UNKNOWN_CARRIER_ID) override val isEmergencyOnly = MutableStateFlow(false) override val isRoaming = MutableStateFlow(false) override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null) 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 f2bb66a501ec..423c47661fa3 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 @@ -593,7 +593,6 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { val realRepo = MobileConnectionRepositoryImpl( - context, SUB_ID, defaultNetworkName = NetworkNameModel.Default("default"), networkNameSeparator = SEP, 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 934e1c64c6da..d1df6e3c2072 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 @@ -42,6 +42,7 @@ import android.telephony.TelephonyManager.DATA_SUSPENDED import android.telephony.TelephonyManager.DATA_UNKNOWN import android.telephony.TelephonyManager.ERI_OFF import android.telephony.TelephonyManager.ERI_ON +import android.telephony.TelephonyManager.EXTRA_CARRIER_ID import android.telephony.TelephonyManager.EXTRA_PLMN import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN import android.telephony.TelephonyManager.EXTRA_SHOW_SPN @@ -116,7 +117,6 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { underTest = MobileConnectionRepositoryImpl( - context, SUB_1_ID, DEFAULT_NAME, SEP, @@ -359,6 +359,36 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { } @Test + fun carrierId_initialValueCaptured() = + testScope.runTest { + whenever(telephonyManager.simCarrierId).thenReturn(1234) + + var latest: Int? = null + val job = underTest.carrierId.onEach { latest = it }.launchIn(this) + + assertThat(latest).isEqualTo(1234) + + job.cancel() + } + + @Test + fun carrierId_updatesOnBroadcast() = + testScope.runTest { + whenever(telephonyManager.simCarrierId).thenReturn(1234) + + var latest: Int? = null + val job = underTest.carrierId.onEach { latest = it }.launchIn(this) + + fakeBroadcastDispatcher.registeredReceivers.forEach { receiver -> + receiver.onReceive(context, carrierIdIntent(carrierId = 4321)) + } + + assertThat(latest).isEqualTo(4321) + + job.cancel() + } + + @Test fun carrierNetworkChange() = testScope.runTest { var latest: Boolean? = null @@ -796,6 +826,15 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager) } + private fun carrierIdIntent( + subId: Int = SUB_1_ID, + carrierId: Int, + ): Intent = + Intent(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED).apply { + putExtra(EXTRA_SUBSCRIPTION_ID, subId) + putExtra(EXTRA_CARRIER_ID, carrierId) + } + private fun spnIntent( subId: Int = SUB_1_ID, showSpn: Boolean = true, 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 9da9ff72d380..4f15aed00230 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 @@ -117,7 +117,6 @@ class MobileConnectionTelephonySmokeTests : SysuiTestCase() { underTest = MobileConnectionRepositoryImpl( - context, SUB_1_ID, DEFAULT_NAME, SEP, 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 ddff17aef2de..9d294cf098e2 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 @@ -155,7 +155,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { connectionFactory = MobileConnectionRepositoryImpl.Factory( fakeBroadcastDispatcher, - context = context, telephonyManager = telephonyManager, bgDispatcher = IMMEDIATE, logger = logger, 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 8d2c5695c7c4..f054422e6524 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 @@ -17,11 +17,11 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor import android.telephony.CellSignalStrength -import com.android.settingslib.SignalIcon import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import kotlinx.coroutines.flow.MutableStateFlow @@ -42,8 +42,10 @@ class FakeMobileIconInteractor( override val mobileIsDefault = MutableStateFlow(true) - private val _iconGroup = MutableStateFlow<SignalIcon.MobileIconGroup>(TelephonyIcons.THREE_G) - override val networkTypeIconGroup = _iconGroup + override val networkTypeIconGroup = + MutableStateFlow<NetworkTypeIconModel>( + NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G) + ) override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo mode")) @@ -73,10 +75,6 @@ class FakeMobileIconInteractor( override val isForceHidden = MutableStateFlow(false) - fun setIconGroup(group: SignalIcon.MobileIconGroup) { - _iconGroup.value = group - } - fun setIsEmergencyOnly(emergency: Boolean) { _isEmergencyOnly.value = emergency } 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 2054e8b12eff..8a515847a415 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 @@ -19,7 +19,8 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor import android.telephony.CellSignalStrength import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN import androidx.test.filters.SmallTest -import com.android.settingslib.SignalIcon.MobileIconGroup +import com.android.settingslib.mobile.MobileIconCarrierIdOverrides +import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState @@ -31,18 +32,24 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobile 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 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.THREE_G +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.yield +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.anyString +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest class MobileIconInteractorTest : SysuiTestCase() { private lateinit var underTest: MobileIconInteractor @@ -50,29 +57,17 @@ class MobileIconInteractorTest : SysuiTestCase() { private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock()) private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock()) - private val scope = CoroutineScope(IMMEDIATE) + private val testDispatcher = UnconfinedTestDispatcher() + private val testScope = TestScope(testDispatcher) @Before fun setUp() { - underTest = - MobileIconInteractorImpl( - scope, - mobileIconsInteractor.activeDataConnectionHasDataEnabled, - mobileIconsInteractor.alwaysShowDataRatIcon, - mobileIconsInteractor.alwaysUseCdmaLevel, - mobileIconsInteractor.mobileIsDefault, - mobileIconsInteractor.defaultMobileIconMapping, - mobileIconsInteractor.defaultMobileIconGroup, - mobileIconsInteractor.defaultDataSubId, - mobileIconsInteractor.isDefaultConnectionFailed, - mobileIconsInteractor.isForceHidden, - connectionRepository, - ) + underTest = createInteractor() } @Test fun gsm_level_default_unknown() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = true var latest: Int? = null @@ -85,7 +80,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun gsm_usesGsmLevel() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = true connectionRepository.primaryLevel.value = GSM_LEVEL connectionRepository.cdmaLevel.value = CDMA_LEVEL @@ -100,7 +95,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = true connectionRepository.primaryLevel.value = GSM_LEVEL connectionRepository.cdmaLevel.value = CDMA_LEVEL @@ -116,7 +111,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_level_default_unknown() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = false var latest: Int? = null @@ -128,7 +123,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = false connectionRepository.primaryLevel.value = GSM_LEVEL connectionRepository.cdmaLevel.value = CDMA_LEVEL @@ -144,7 +139,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.isGsm.value = false connectionRepository.primaryLevel.value = GSM_LEVEL connectionRepository.cdmaLevel.value = CDMA_LEVEL @@ -160,7 +155,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun numberOfLevels_comesFromRepo() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Int? = null val job = underTest.numberOfLevels.onEach { latest = it }.launchIn(this) @@ -175,101 +170,128 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_three_g() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(TelephonyIcons.THREE_G) + assertThat(latest).isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)) job.cancel() } @Test fun iconGroup_updates_on_change() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G)) - yield() - assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G) + assertThat(latest).isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.FOUR_G)) job.cancel() } @Test fun iconGroup_5g_override_type() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.resolvedNetworkType.value = OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE)) - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(TelephonyIcons.NR_5G) + assertThat(latest).isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.NR_5G)) job.cancel() } @Test fun iconGroup_default_if_no_lookup() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)) - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(FakeMobileIconsInteractor.DEFAULT_ICON) + assertThat(latest) + .isEqualTo(NetworkTypeIconModel.DefaultIcon(FakeMobileIconsInteractor.DEFAULT_ICON)) job.cancel() } @Test fun iconGroup_carrierMerged_usesOverride() = - runBlocking(IMMEDIATE) { + testScope.runTest { connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(CarrierMergedNetworkType.iconGroupOverride) + assertThat(latest) + .isEqualTo( + NetworkTypeIconModel.DefaultIcon(CarrierMergedNetworkType.iconGroupOverride) + ) job.cancel() } @Test fun `icon group - checks default data`() = - runBlocking(IMMEDIATE) { + testScope.runTest { mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - var latest: MobileIconGroup? = null + var latest: NetworkTypeIconModel? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - assertThat(latest).isEqualTo(TelephonyIcons.THREE_G) + assertThat(latest).isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)) // Default data sub id changes to something else mobileIconsInteractor.defaultDataSubId.value = 123 - yield() - assertThat(latest).isEqualTo(TelephonyIcons.NOT_DEFAULT_DATA) + assertThat(latest) + .isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.NOT_DEFAULT_DATA)) + + job.cancel() + } + + @Test + fun overrideIcon_usesCarrierIdOverride() = + testScope.runTest { + val overrides = + mock<MobileIconCarrierIdOverrides>().also { + whenever(it.carrierIdEntryExists(anyInt())).thenReturn(true) + whenever(it.getOverrideFor(anyInt(), anyString(), any())).thenReturn(1234) + } + + underTest = createInteractor(overrides) + + mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) + + var latest: NetworkTypeIconModel? = null + val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) + + assertThat(latest) + .isEqualTo(NetworkTypeIconModel.OverriddenIcon(TelephonyIcons.THREE_G, 1234)) job.cancel() } @Test fun alwaysShowDataRatIcon_matchesParent() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this) @@ -284,7 +306,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun alwaysUseCdmaLevel_matchesParent() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this) @@ -299,7 +321,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun test_isDefaultDataEnabled_matchesParent() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isDefaultDataEnabled.onEach { latest = it }.launchIn(this) @@ -314,7 +336,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun test_isDefaultConnectionFailed_matchedParent() = - runBlocking(IMMEDIATE) { + testScope.runTest { val job = underTest.isDefaultConnectionFailed.launchIn(this) mobileIconsInteractor.isDefaultConnectionFailed.value = false @@ -328,12 +350,11 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun dataState_connected() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this) connectionRepository.dataConnectionState.value = DataConnectionState.Connected - yield() assertThat(latest).isTrue() @@ -342,7 +363,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun dataState_notConnected() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this) @@ -355,7 +376,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun `isInService - uses repository value`() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isInService.onEach { latest = it }.launchIn(this) @@ -372,19 +393,17 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun `roaming - is gsm - uses connection model`() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) connectionRepository.cdmaRoaming.value = true connectionRepository.isGsm.value = true connectionRepository.isRoaming.value = false - yield() assertThat(latest).isFalse() connectionRepository.isRoaming.value = true - yield() assertThat(latest).isTrue() @@ -393,21 +412,19 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun `roaming - is cdma - uses cdma roaming bit`() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) connectionRepository.cdmaRoaming.value = false connectionRepository.isGsm.value = false connectionRepository.isRoaming.value = true - yield() assertThat(latest).isFalse() connectionRepository.cdmaRoaming.value = true connectionRepository.isGsm.value = false connectionRepository.isRoaming.value = false - yield() assertThat(latest).isTrue() @@ -416,7 +433,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun `roaming - false while carrierNetworkChangeActive`() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) @@ -424,13 +441,11 @@ class MobileIconInteractorTest : SysuiTestCase() { connectionRepository.isGsm.value = false connectionRepository.isRoaming.value = true connectionRepository.carrierNetworkChangeActive.value = true - yield() assertThat(latest).isFalse() connectionRepository.cdmaRoaming.value = true connectionRepository.isGsm.value = true - yield() assertThat(latest).isFalse() @@ -439,7 +454,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun `network name - uses operatorAlphaShot when non null and repo is default`() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: NetworkNameModel? = null val job = underTest.networkName.onEach { latest = it }.launchIn(this) @@ -448,20 +463,17 @@ class MobileIconInteractorTest : SysuiTestCase() { // Default network name, operator name is non-null, uses the operator name connectionRepository.networkName.value = DEFAULT_NAME connectionRepository.operatorAlphaShort.value = testOperatorName - yield() assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName)) // Default network name, operator name is null, uses the default connectionRepository.operatorAlphaShort.value = null - yield() assertThat(latest).isEqualTo(DEFAULT_NAME) // Derived network name, operator name non-null, uses the derived name connectionRepository.networkName.value = DERIVED_NAME connectionRepository.operatorAlphaShort.value = testOperatorName - yield() assertThat(latest).isEqualTo(DERIVED_NAME) @@ -470,7 +482,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun isForceHidden_matchesParent() = - runBlocking(IMMEDIATE) { + testScope.runTest { var latest: Boolean? = null val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this) @@ -483,9 +495,26 @@ class MobileIconInteractorTest : SysuiTestCase() { job.cancel() } - companion object { - private val IMMEDIATE = Dispatchers.Main.immediate + private fun createInteractor( + overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl() + ) = + MobileIconInteractorImpl( + testScope.backgroundScope, + mobileIconsInteractor.activeDataConnectionHasDataEnabled, + mobileIconsInteractor.alwaysShowDataRatIcon, + mobileIconsInteractor.alwaysUseCdmaLevel, + mobileIconsInteractor.mobileIsDefault, + mobileIconsInteractor.defaultMobileIconMapping, + mobileIconsInteractor.defaultMobileIconGroup, + mobileIconsInteractor.defaultDataSubId, + mobileIconsInteractor.isDefaultConnectionFailed, + mobileIconsInteractor.isForceHidden, + connectionRepository, + context, + overrides, + ) + companion object { private const val GSM_LEVEL = 1 private const val CDMA_LEVEL = 2 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 898e89770394..c5ceacac6446 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 @@ -88,6 +88,7 @@ class MobileIconsInteractorTest : SysuiTestCase() { connectivityRepository, userSetupRepository, testScope.backgroundScope, + context, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt index a6d915243f60..e99be864e73f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt @@ -24,6 +24,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants @@ -71,9 +72,9 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() { setLevel(1) setIsDefaultDataEnabled(true) setIsFailedConnection(false) - setIconGroup(TelephonyIcons.THREE_G) setIsEmergencyOnly(false) setNumberOfLevels(4) + networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G) isDataConnected.value = true } commonImpl = diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt index 1593e5c735a5..292e34c650bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor +import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel @@ -77,9 +78,9 @@ class MobileIconViewModelTest : SysuiTestCase() { setLevel(1) setIsDefaultDataEnabled(true) setIsFailedConnection(false) - setIconGroup(THREE_G) setIsEmergencyOnly(false) setNumberOfLevels(4) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) isDataConnected.value = true } createAndSetViewModel() @@ -256,7 +257,7 @@ class MobileIconViewModelTest : SysuiTestCase() { THREE_G.dataType, ContentDescription.Resource(THREE_G.dataContentDescription) ) - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) @@ -269,7 +270,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun networkType_nullWhenDisabled() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(false) var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) @@ -282,7 +283,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun networkType_nullWhenFailedConnection() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(true) interactor.setIsFailedConnection(true) var latest: Icon? = null @@ -302,11 +303,11 @@ class MobileIconViewModelTest : SysuiTestCase() { ContentDescription.Resource(THREE_G.dataContentDescription) ) - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) assertThat(latest).isEqualTo(initial) interactor.isDataConnected.value = false @@ -325,7 +326,7 @@ class MobileIconViewModelTest : SysuiTestCase() { THREE_G.dataType, ContentDescription.Resource(THREE_G.dataContentDescription) ) - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(true) var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) @@ -343,7 +344,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun networkType_alwaysShow_shownEvenWhenDisabled() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(false) interactor.alwaysShowDataRatIcon.value = true @@ -363,7 +364,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun networkType_alwaysShow_shownEvenWhenDisconnected() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.isDataConnected.value = false interactor.alwaysShowDataRatIcon.value = true @@ -383,7 +384,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun networkType_alwaysShow_shownEvenWhenFailedConnection() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsFailedConnection(true) interactor.alwaysShowDataRatIcon.value = true @@ -404,7 +405,7 @@ class MobileIconViewModelTest : SysuiTestCase() { fun networkType_alwaysShow_notShownWhenInvalidDataTypeIcon() = testScope.runTest { // The UNKNOWN icon group doesn't have a valid data type icon ID - interactor.setIconGroup(UNKNOWN) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(UNKNOWN) interactor.alwaysShowDataRatIcon.value = true var latest: Icon? = null @@ -418,7 +419,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun `network type - alwaysShow - shown when not default`() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.mobileIsDefault.value = false interactor.alwaysShowDataRatIcon.value = true @@ -438,7 +439,7 @@ class MobileIconViewModelTest : SysuiTestCase() { @Test fun `network type - not shown when not default`() = testScope.runTest { - interactor.setIconGroup(THREE_G) + interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.isDataConnected.value = true interactor.mobileIsDefault.value = false |