From 21a25876b3104cfc70926cd90c69ef04b6d13dd8 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Thu, 9 Mar 2023 10:40:51 -0500 Subject: [PATCH 1/2] [Sb refactor] Add carrierId to the new pipeline Adds carrierId to the mobile connection repo, and upgrades the mobile icon group type to a NetworkTypeIconModel so that we can do fancy stuff like override it. We add support for checking MobileIconCarrierIdOverrides for an override entry whenever the carrierId changes. If an override entry exists, then we check for an asset override whenever the network changes. Also can be tested using Demo mode: ``` $ # MCC/MNC 311/480 overrides the icon to use 5GUC -- no carrierId $ # override for 1234 $ adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 2 -e datatype 5g+ -e mccmnc 311480 -e carrierid 1234 $ # carrierid 2032 contains an icon override, pointing back to the $ # default 5G+ icon $ adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 2 -e datatype 5g+ -e mccmnc 311480 -e carrierid 2032 ``` Test: MobileConnectionsRepositoryTest Test: MobileIconInteractorTest Bug: 272099695 Change-Id: Ia71831d481d84c2508d8cbe08755644eed2f9ff5 --- .../phone/StatusBarIconController.java | 4 +- .../repository/MobileConnectionRepository.kt | 3 + .../demo/DemoMobileConnectionRepository.kt | 17 ++ .../prod/CarrierMergedConnectionRepository.kt | 2 + .../prod/FullMobileConnectionRepository.kt | 20 +- .../prod/MobileConnectionRepositoryImpl.kt | 27 ++- .../domain/interactor/MobileIconInteractor.kt | 73 ++++++-- .../interactor/MobileIconsInteractor.kt | 3 + .../domain/model/NetworkTypeIconModel.kt | 69 +++++++ .../ui/viewmodel/MobileIconViewModel.kt | 8 +- .../FakeMobileConnectionRepository.kt | 2 + .../FullMobileConnectionRepositoryTest.kt | 1 - .../prod/MobileConnectionRepositoryTest.kt | 41 ++++- .../MobileConnectionTelephonySmokeTests.kt | 1 - .../prod/MobileConnectionsRepositoryTest.kt | 1 - .../interactor/FakeMobileIconInteractor.kt | 12 +- .../interactor/MobileIconInteractorTest.kt | 173 ++++++++++-------- .../interactor/MobileIconsInteractorTest.kt | 1 + .../LocationBasedMobileIconViewModelTest.kt | 3 +- .../ui/viewmodel/MobileIconViewModelTest.kt | 27 +-- 20 files changed, 360 insertions(+), 128 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/model/NetworkTypeIconModel.kt 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 30d2295206d84..a8a834f1e8f49 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 90c32dc080450..3a11635f75c34 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 + /** * 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 809772eec2f0f..6b86432b8171f 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 94d6d0b1db44a..a609917351d99 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 b3737ecd1e0bc..8869dfe026975 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_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_PRIMARY_LEVEL = "primaryLevel" + 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_IS_GSM = "isGsm" + const val COL_IS_IN_SERVICE = "isInService" + const val COL_OPERATOR = "operatorName" + const val COL_PRIMARY_LEVEL = "primaryLevel" + 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 d0c6215a55d8f..b475183d98c69 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 = 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 22351f8b28215..1c5ca6bbea211 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 /** Observable for RAT type (network type) indicator */ - val networkTypeIconGroup: StateFlow + val networkTypeIconGroup: StateFlow /** * Provider name for this network connection. The name can be one of 3 values: @@ -123,6 +129,8 @@ class MobileIconInteractorImpl( override val isDefaultConnectionFailed: StateFlow, override val isForceHidden: Flow, 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 = + /** What the mobile icon would be before carrierId overrides */ + private val defaultNetworkType: StateFlow = combine( connectionRepository.resolvedNetworkType, defaultMobileIconMapping, @@ -172,20 +189,46 @@ class MobileIconInteractorImpl( when (resolvedNetworkType) { is ResolvedNetworkType.CarrierMergedNetworkType -> resolvedNetworkType.iconGroupOverride - else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup + else -> { + mapping[resolvedNetworkType.lookupKey] ?: defaultGroup + } + } + } + .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() - .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) + .logDiffsForTable( + tableLogBuffer = tableLogBuffer, + columnPrefix = "", + initialValue = DefaultIcon(defaultMobileIconGroup.value), + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + DefaultIcon(defaultMobileIconGroup.value), + ) override val isEmergencyOnly = connectionRepository.isEmergencyOnly 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 6c8310ac3d294..7ec9ed8ccf2d0 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 0000000000000..6ea5f90ddc713 --- /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 { + 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 62bc27f9dd4e3..50877eb4c72c2 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 44fbd5b99894c..6306a36d9730a 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 = 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 f2bb66a501ec1..423c47661fa3f 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 934e1c64c6da3..d1df6e3c20723 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, @@ -358,6 +358,36 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { job.cancel() } + @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 { @@ -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 9da9ff72d3800..4f15aed00230b 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 ddff17aef2dea..9d294cf098e2e 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 8d2c5695c7c4b..f054422e65245 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(TelephonyIcons.THREE_G) - override val networkTypeIconGroup = _iconGroup + override val networkTypeIconGroup = + MutableStateFlow( + 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 2054e8b12efff..8a515847a415f 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().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 898e897703946..c5ceacac64467 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 a6d915243f60d..e99be864e73fd 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 1593e5c735a55..292e34c650bb2 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 From 1e79aacc1fe81b2136d964e541842f48ef0bd2f9 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Tue, 28 Mar 2023 18:55:10 -0400 Subject: [PATCH 2/2] [Sb refactor] Remove the concept of `isDefault` I feel like this CL deserves some introspection as to what is going on. INTRO The old pipeline has two main concepts that it tracks when it comes to knowing which subscription is special: `active` and `default`. They come from static methods on `SubscriptionManager`: getActiveDataSubscriptionId and getDefaultDataSubscriptionId. The old pipeline will map from `networkType` to icon group except for the following cases. For each subscription: 1. When !telephonyManager.isDataConnectionAllowed (!dataEnabled) AND the defaultDataSubId is not the current subscription, set the MobileIconGroup to NOT_DEFAULT_DATA. 2. When !dataEnabled AND this is the defaultDataSubId, set the MobileIconGroup to DATA_DISABLED. Note that neither of these icon groups represent icons, they have a resId of 0, meaning that later on when it comes time to use them, they will _not_ show any UI on screen, nor will their content descriptions be used. Also note that this is just system state stored in an UI view model-like class. THE PROBLEM So, the question becomes: what do we do with these two mobile icon groups in the new pipeline? Do we use the same input logic as the old pipeline and thread these two special-case MobileIconGroups through the MobileIconInteractor and then filter them out at the View Model? Or can we rework the system to be smarter? THIS CHANGE Note that from the intro we stated that both of these cases only apply when telephony reports `false` for `isDataConnectionAllowed`. Only _then_ does the old pipeline do anything with these icon groups. This means that as far as the UI is concerned, NOT_DEFAULT_DATA and DATA_DISABLED are equivalent (showing no UI). The only time that NOT_DEFAULT_DATA comes into play is when determining when to show the exclamation mark. Side note, there is a related bug in the old pipeline about checking NOT_DEFAULT_DATA. When NetworkControllerIpml is attempting to find out which controller is the data controller, it checks against the _active_ data subscriptio ID vs the _default_. This probably doesn't account for a huge amount of bugs, but it's worth mentioning this problem. With all of that out of the way, this change is rather simple: *remove the concept of `isDefault` from the pipeline*. The only thing we need to track is whether or not to show the data icon. The only remaining relevant piece to track was the exclamation mark on the triangle, but that field is covered elsewhere by a more appropriately-named field tracking the active data. Test: MobileIconInteractorTest Test: MobileIconViewModelTest Bug: 274724674 Bug: 270621876 Change-Id: I508a87e597cda5f9351053266701ebec84a0bcc3 --- .../domain/interactor/MobileIconInteractor.kt | 19 +-------------- .../interactor/MobileIconsInteractor.kt | 6 ----- .../ui/viewmodel/MobileIconViewModel.kt | 5 ++-- .../interactor/FakeMobileIconsInteractor.kt | 1 - .../interactor/MobileIconInteractorTest.kt | 23 ------------------- .../ui/viewmodel/MobileIconViewModelTest.kt | 15 ++++++++---- 6 files changed, 14 insertions(+), 55 deletions(-) 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 1c5ca6bbea211..b36ba3845fe90 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 @@ -21,7 +21,6 @@ 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 @@ -41,7 +40,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.stateIn interface MobileIconInteractor { @@ -125,7 +123,6 @@ class MobileIconInteractorImpl( override val mobileIsDefault: StateFlow, defaultMobileIconMapping: StateFlow>, defaultMobileIconGroup: StateFlow, - defaultDataSubId: StateFlow, override val isDefaultConnectionFailed: StateFlow, override val isForceHidden: Flow, connectionRepository: MobileConnectionRepository, @@ -138,15 +135,6 @@ class MobileIconInteractorImpl( override val isDataEnabled: StateFlow = connectionRepository.dataEnabled - private val isDefault = - defaultDataSubId - .mapLatest { connectionRepository.subId == it } - .stateIn( - scope, - SharingStarted.WhileSubscribed(), - 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 @@ -180,12 +168,7 @@ class MobileIconInteractorImpl( connectionRepository.resolvedNetworkType, defaultMobileIconMapping, defaultMobileIconGroup, - isDefault, - ) { resolvedNetworkType, mapping, defaultGroup, isDefault -> - if (!isDefault) { - return@combine NOT_DEFAULT_DATA - } - + ) { resolvedNetworkType, mapping, defaultGroup -> when (resolvedNetworkType) { is ResolvedNetworkType.CarrierMergedNetworkType -> resolvedNetworkType.iconGroupOverride 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 7ec9ed8ccf2d0..1e3122b1a5158 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,9 +76,6 @@ interface MobileIconsInteractor { /** True if the CDMA level should be preferred over the primary level. */ val alwaysUseCdmaLevel: StateFlow - /** Tracks the subscriptionId set as the default for data connections */ - val defaultDataSubId: StateFlow - /** The icon mapping from network type to [MobileIconGroup] for the default subscription */ val defaultMobileIconMapping: StateFlow> @@ -186,8 +183,6 @@ constructor( ) .stateIn(scope, SharingStarted.WhileSubscribed(), listOf()) - override val defaultDataSubId = mobileConnectionsRepo.defaultDataSubId - /** * Copied from the old pipeline. We maintain a 2s period of time where we will keep the * validated bit from the old active network (A) while data is changing to the new one (B). @@ -284,7 +279,6 @@ constructor( mobileIsDefault, defaultMobileIconMapping, defaultMobileIconGroup, - defaultDataSubId, isDefaultConnectionFailed, isForceHidden, mobileConnectionsRepo.getRepoForSubId(subId), 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 50877eb4c72c2..dce7bf21faddd 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 @@ -146,11 +146,10 @@ constructor( combine( iconInteractor.isDataConnected, iconInteractor.isDataEnabled, - iconInteractor.isDefaultConnectionFailed, iconInteractor.alwaysShowDataRatIcon, iconInteractor.mobileIsDefault, - ) { dataConnected, dataEnabled, failedConnection, alwaysShow, mobileIsDefault -> - alwaysShow || (dataConnected && dataEnabled && !failedConnection && mobileIsDefault) + ) { dataConnected, dataEnabled, alwaysShow, mobileIsDefault -> + alwaysShow || (dataEnabled && dataConnected && mobileIsDefault) } .distinctUntilChanged() .logDiffsForTable( 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 d6fdad417b319..3ced7b2c4e6e2 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 @@ -59,7 +59,6 @@ class FakeMobileIconsInteractor( override val alwaysShowDataRatIcon = MutableStateFlow(false) override val alwaysUseCdmaLevel = MutableStateFlow(false) - override val defaultDataSubId = MutableStateFlow(DEFAULT_DATA_SUB_ID) override val mobileIsDefault = MutableStateFlow(false) 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 8a515847a415f..8d7f0f6035cc7 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 @@ -244,27 +244,6 @@ class MobileIconInteractorTest : SysuiTestCase() { job.cancel() } - @Test - fun `icon group - checks default data`() = - testScope.runTest { - 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.DefaultIcon(TelephonyIcons.THREE_G)) - - // Default data sub id changes to something else - mobileIconsInteractor.defaultDataSubId.value = 123 - - assertThat(latest) - .isEqualTo(NetworkTypeIconModel.DefaultIcon(TelephonyIcons.NOT_DEFAULT_DATA)) - - job.cancel() - } - @Test fun overrideIcon_usesCarrierIdOverride() = testScope.runTest { @@ -276,7 +255,6 @@ class MobileIconInteractorTest : SysuiTestCase() { underTest = createInteractor(overrides) - mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID connectionRepository.resolvedNetworkType.value = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) @@ -506,7 +484,6 @@ class MobileIconInteractorTest : SysuiTestCase() { mobileIconsInteractor.mobileIsDefault, mobileIconsInteractor.defaultMobileIconMapping, mobileIconsInteractor.defaultMobileIconGroup, - mobileIconsInteractor.defaultDataSubId, mobileIconsInteractor.isDefaultConnectionFailed, mobileIconsInteractor.isForceHidden, connectionRepository, 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 292e34c650bb2..1b6ab4d7af966 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 @@ -268,10 +268,11 @@ class MobileIconViewModelTest : SysuiTestCase() { } @Test - fun networkType_nullWhenDisabled() = + fun networkType_null_whenDisabled() = testScope.runTest { interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(false) + interactor.mobileIsDefault.value = true var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) @@ -281,15 +282,21 @@ class MobileIconViewModelTest : SysuiTestCase() { } @Test - fun networkType_nullWhenFailedConnection() = + fun networkTypeIcon_notNull_whenEnabled() = testScope.runTest { + val expected = + Icon.Resource( + THREE_G.dataType, + ContentDescription.Resource(THREE_G.dataContentDescription) + ) interactor.networkTypeIconGroup.value = NetworkTypeIconModel.DefaultIcon(THREE_G) interactor.setIsDataEnabled(true) - interactor.setIsFailedConnection(true) + interactor.isDataConnected.value = true + interactor.mobileIsDefault.value = true var latest: Icon? = null val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this) - assertThat(latest).isNull() + assertThat(latest).isEqualTo(expected) job.cancel() }