summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/model/NetworkTypeIconModel.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt173
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt27
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