From 5cbcba28d6653db74156e82ca26529e1546c55e9 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Fri, 24 Feb 2023 17:44:52 -0500 Subject: [PATCH 1/3] [Sb refactor] Remove MobileConnectionModel Rationale: MobileConnectionModel was loosely a representative data object for the colletion of TelephonyCallbacks that we register on a per-subscription basis. However, this data object only existed in the boundary between MobileConnectionRepository -> MobileIconInteractor, and was immediately unboxed into the relevant fields for use in business logic. This meant that the entire object was being collected even if a downstream client only relied on one field. Ultimately, this leads to extra work being done, and extra logs being written (e.g., DataActivity logs heppning even when the config to show the activity was false). The objective of this CL is _only_ to unbox the fields from MobileConnectionModel, and to represent each field as a separate property on the connection directly. The underlying implementation still registers only a single callback with every listener, but the repository breaks out every callback into its own flow immediately. Test: test in com.android.systemui.statusbar.pipeline.mobile Bug: 270300839 Change-Id: I8b62ae3367643143c6f36b689c65ab40e65c4510 --- .../mobile/data/model/DataConnectionState.kt | 16 +- .../data/model/MobileConnectionModel.kt | 176 --------------- .../mobile/data/model/ResolvedNetworkType.kt | 18 +- .../repository/MobileConnectionRepository.kt | 57 ++++- .../demo/DemoMobileConnectionsRepository.kt | 154 +++++++++---- .../prod/CarrierMergedConnectionRepository.kt | 83 ++++--- .../prod/FullMobileConnectionRepository.kt | 151 ++++++++++++- .../prod/MobileConnectionRepositoryImpl.kt | 175 +++++++------- .../domain/interactor/MobileIconInteractor.kt | 65 +++--- .../data/model/MobileConnectionModelTest.kt | 106 --------- .../FakeMobileConnectionRepository.kt | 23 +- .../DemoMobileConnectionParameterizedTest.kt | 19 +- .../DemoMobileConnectionsRepositoryTest.kt | 36 ++- .../CarrierMergedConnectionRepositoryTest.kt | 106 ++++----- .../FullMobileConnectionRepositoryTest.kt | 213 +++++++++--------- .../prod/MobileConnectionRepositoryTest.kt | 206 +++++++++-------- .../interactor/MobileIconInteractorTest.kt | 173 ++++---------- 17 files changed, 872 insertions(+), 905 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt index 85729c12cd4c0..19f0242040fd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt @@ -24,9 +24,11 @@ import android.telephony.TelephonyManager.DATA_HANDOVER_IN_PROGRESS import android.telephony.TelephonyManager.DATA_SUSPENDED import android.telephony.TelephonyManager.DATA_UNKNOWN import android.telephony.TelephonyManager.DataState +import com.android.systemui.log.table.Diffable +import com.android.systemui.log.table.TableRowLogger /** Internal enum representation of the telephony data connection states */ -enum class DataConnectionState { +enum class DataConnectionState : Diffable { Connected, Connecting, Disconnected, @@ -34,7 +36,17 @@ enum class DataConnectionState { Suspended, HandoverInProgress, Unknown, - Invalid, + Invalid; + + override fun logDiffs(prevVal: DataConnectionState, row: TableRowLogger) { + if (prevVal != this) { + row.logChange(COL_CONNECTION_STATE, name) + } + } + + companion object { + private const val COL_CONNECTION_STATE = "connectionState" + } } fun @receiver:DataState Int.toDataConnectionType(): DataConnectionState = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt deleted file mode 100644 index ed7f60b50bb9f..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2022 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.data.model - -import android.annotation.IntRange -import android.telephony.CellSignalStrength -import android.telephony.TelephonyCallback.CarrierNetworkListener -import android.telephony.TelephonyCallback.DataActivityListener -import android.telephony.TelephonyCallback.DataConnectionStateListener -import android.telephony.TelephonyCallback.DisplayInfoListener -import android.telephony.TelephonyCallback.ServiceStateListener -import android.telephony.TelephonyCallback.SignalStrengthsListener -import android.telephony.TelephonyDisplayInfo -import android.telephony.TelephonyManager -import androidx.annotation.VisibleForTesting -import com.android.systemui.log.table.Diffable -import com.android.systemui.log.table.TableRowLogger -import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected -import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel - -/** - * Data class containing all of the relevant information for a particular line of service, known as - * a Subscription in the telephony world. These models are the result of a single telephony listener - * which has many callbacks which each modify some particular field on this object. - * - * The design goal here is to de-normalize fields from the system into our model fields below. So - * any new field that needs to be tracked should be copied into this data class rather than - * threading complex system objects through the pipeline. - */ -data class MobileConnectionModel( - /** Fields below are from [ServiceStateListener.onServiceStateChanged] */ - val isEmergencyOnly: Boolean = false, - val isRoaming: Boolean = false, - /** - * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the - * current registered operator name in short alphanumeric format. In some cases this name might - * be preferred over other methods of calculating the network name - */ - val operatorAlphaShort: String? = null, - - /** - * TODO (b/263167683): Clarify this field - * - * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a - * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a - * connection to be in-service if either the voice registration state is IN_SERVICE or the data - * registration state is IN_SERVICE and NOT IWLAN. - */ - val isInService: Boolean = false, - - /** Fields below from [SignalStrengthsListener.onSignalStrengthsChanged] */ - val isGsm: Boolean = false, - @IntRange(from = 0, to = 4) - val cdmaLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, - @IntRange(from = 0, to = 4) - val primaryLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, - - /** Fields below from [DataConnectionStateListener.onDataConnectionStateChanged] */ - val dataConnectionState: DataConnectionState = Disconnected, - - /** - * Fields below from [DataActivityListener.onDataActivity]. See [TelephonyManager] for the - * values - */ - val dataActivityDirection: DataActivityModel = - DataActivityModel( - hasActivityIn = false, - hasActivityOut = false, - ), - - /** Fields below from [CarrierNetworkListener.onCarrierNetworkChange] */ - val carrierNetworkChangeActive: Boolean = false, - - /** Fields below from [DisplayInfoListener.onDisplayInfoChanged]. */ - - /** - * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or - * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon - */ - val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType, -) : Diffable { - override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) { - if (prevVal.dataConnectionState != dataConnectionState) { - row.logChange(COL_CONNECTION_STATE, dataConnectionState.name) - } - - if (prevVal.isEmergencyOnly != isEmergencyOnly) { - row.logChange(COL_EMERGENCY, isEmergencyOnly) - } - - if (prevVal.isRoaming != isRoaming) { - row.logChange(COL_ROAMING, isRoaming) - } - - if (prevVal.operatorAlphaShort != operatorAlphaShort) { - row.logChange(COL_OPERATOR, operatorAlphaShort) - } - - if (prevVal.isInService != isInService) { - row.logChange(COL_IS_IN_SERVICE, isInService) - } - - if (prevVal.isGsm != isGsm) { - row.logChange(COL_IS_GSM, isGsm) - } - - if (prevVal.cdmaLevel != cdmaLevel) { - row.logChange(COL_CDMA_LEVEL, cdmaLevel) - } - - if (prevVal.primaryLevel != primaryLevel) { - row.logChange(COL_PRIMARY_LEVEL, primaryLevel) - } - - if (prevVal.dataActivityDirection.hasActivityIn != dataActivityDirection.hasActivityIn) { - row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn) - } - - if (prevVal.dataActivityDirection.hasActivityOut != dataActivityDirection.hasActivityOut) { - row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut) - } - - if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) { - row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive) - } - - if (prevVal.resolvedNetworkType != resolvedNetworkType) { - row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString()) - } - } - - override fun logFull(row: TableRowLogger) { - row.logChange(COL_CONNECTION_STATE, dataConnectionState.name) - row.logChange(COL_EMERGENCY, isEmergencyOnly) - row.logChange(COL_ROAMING, isRoaming) - row.logChange(COL_OPERATOR, operatorAlphaShort) - row.logChange(COL_IS_IN_SERVICE, isInService) - row.logChange(COL_IS_GSM, isGsm) - row.logChange(COL_CDMA_LEVEL, cdmaLevel) - row.logChange(COL_PRIMARY_LEVEL, primaryLevel) - row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn) - row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut) - row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive) - row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString()) - } - - @VisibleForTesting - 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_CONNECTION_STATE = "ConnectionState" - const val COL_ACTIVITY_DIRECTION_IN = "DataActivity.In" - const val COL_ACTIVITY_DIRECTION_OUT = "DataActivity.Out" - const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive" - const val COL_RESOLVED_NETWORK_TYPE = "NetworkType" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt index 5562e73f04784..bacf34fa2d606 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.pipeline.mobile.data.model import android.telephony.Annotation.NetworkType import com.android.settingslib.SignalIcon import com.android.settingslib.mobile.TelephonyIcons +import com.android.systemui.log.table.Diffable +import com.android.systemui.log.table.TableRowLogger import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy /** @@ -26,11 +28,19 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy * on whether or not the display info contains an override type, we may have to call different * methods on [MobileMappingsProxy] to generate an icon lookup key. */ -sealed interface ResolvedNetworkType { +sealed interface ResolvedNetworkType : Diffable { val lookupKey: String + override fun logDiffs(prevVal: ResolvedNetworkType, row: TableRowLogger) { + if (prevVal != this) { + row.logChange(COL_NETWORK_TYPE, this.toString()) + } + } + object UnknownNetworkType : ResolvedNetworkType { override val lookupKey: String = "unknown" + + override fun toString(): String = "Unknown" } data class DefaultNetworkType( @@ -47,5 +57,11 @@ sealed interface ResolvedNetworkType { override val lookupKey: String = "cwf" val iconGroupOverride: SignalIcon.MobileIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI + + override fun toString(): String = "CarrierMerged" + } + + companion object { + private const val COL_NETWORK_TYPE = "networkType" } } 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 6187f64e011d9..90c32dc080450 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 @@ -17,11 +17,12 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository import android.telephony.SubscriptionInfo -import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType +import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import kotlinx.coroutines.flow.StateFlow /** @@ -45,11 +46,57 @@ interface MobileConnectionRepository { */ val tableLogBuffer: TableLogBuffer + /** True if the [android.telephony.ServiceState] says this connection is emergency calls only */ + val isEmergencyOnly: StateFlow + + /** True if [android.telephony.ServiceState] says we are roaming */ + val isRoaming: StateFlow + /** - * A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single - * listener + model. + * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the + * current registered operator name in short alphanumeric format. In some cases this name might + * be preferred over other methods of calculating the network name */ - val connectionInfo: StateFlow + val operatorAlphaShort: StateFlow + + /** + * TODO (b/263167683): Clarify this field + * + * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a + * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a + * connection to be in-service if either the voice registration state is IN_SERVICE or the data + * registration state is IN_SERVICE and NOT IWLAN. + */ + val isInService: StateFlow + + /** True if [android.telephony.SignalStrength] told us that this connection is using GSM */ + val isGsm: StateFlow + + /** + * There is still specific logic in the pipeline that calls out CDMA level explicitly. This + * field is not completely orthogonal to [primaryLevel], because CDMA could be primary. + */ + // @IntRange(from = 0, to = 4) + val cdmaLevel: StateFlow + + /** [android.telephony.SignalStrength]'s concept of the overall signal level */ + // @IntRange(from = 0, to = 4) + val primaryLevel: StateFlow + + /** The current data connection state. See [DataConnectionState] */ + val dataConnectionState: StateFlow + + /** The current data activity direction. See [DataActivityModel] */ + val dataActivityDirection: StateFlow + + /** True if there is currently a carrier network change in process */ + val carrierNetworkChangeActive: StateFlow + + /** + * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or + * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon + */ + val resolvedNetworkType: StateFlow /** The total number of levels. Used with [SignalDrawable]. */ val numberOfLevels: StateFlow diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt index e924832321869..2b66758bb4b53 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt @@ -17,8 +17,9 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo import android.content.Context +import android.telephony.CellSignalStrength import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID -import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE +import android.telephony.TelephonyManager import android.util.Log import com.android.settingslib.SignalIcon import com.android.settingslib.mobile.MobileMappings @@ -27,20 +28,18 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository -import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled -import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE +import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel @@ -53,6 +52,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -183,7 +183,7 @@ constructor( private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer { val tableLogBuffer = logFactory.getOrCreate( - "DemoMobileConnectionLog [$subId]", + "DemoMobileConnectionLog[$subId]", MOBILE_CONNECTION_BUFFER_SIZE, ) @@ -237,23 +237,18 @@ constructor( } } - private fun processEnabledMobileState(state: Mobile) { + private fun processEnabledMobileState(event: Mobile) { // get or create the connection repo, and set its values - val subId = state.subId ?: DEFAULT_SUB_ID + val subId = event.subId ?: DEFAULT_SUB_ID maybeCreateSubscription(subId) val connection = getRepoForSubId(subId) - connectionRepoCache[subId]?.lastMobileState = state + connectionRepoCache[subId]?.lastMobileState = event // TODO(b/261029387): until we have a command, use the most recent subId defaultDataSubId.value = subId - // This is always true here, because we split out disabled states at the data-source level - connection.dataEnabled.value = true - connection.networkName.value = NetworkNameModel.IntentDerived(state.name) - - connection.cdmaRoaming.value = state.roaming - connection.connectionInfo.value = state.toMobileConnectionModel() + connection.processDemoMobileEvent(event, event.dataType.toResolvedNetworkType()) } private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) { @@ -272,13 +267,7 @@ constructor( defaultDataSubId.value = subId val connection = getRepoForSubId(subId) - // This is always true here, because we split out disabled states at the data-source level - connection.dataEnabled.value = true - connection.networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME) - connection.numberOfLevels.value = event.numberOfLevels - connection.cdmaRoaming.value = false - connection.connectionInfo.value = event.toMobileConnectionModel() - Log.e("CCS", "output connection info = ${connection.connectionInfo.value}") + connection.processCarrierMergedEvent(event) } private fun maybeRemoveSubscription(subId: Int?) { @@ -332,29 +321,6 @@ constructor( private fun subIdsString(): String = _subscriptions.value.joinToString(",") { it.subscriptionId.toString() } - private fun Mobile.toMobileConnectionModel(): MobileConnectionModel { - return MobileConnectionModel( - isEmergencyOnly = false, // TODO(b/261029387): not yet supported - isRoaming = roaming, - isInService = (level ?: 0) > 0, - isGsm = false, // TODO(b/261029387): not yet supported - cdmaLevel = level ?: 0, - primaryLevel = level ?: 0, - dataConnectionState = - DataConnectionState.Connected, // TODO(b/261029387): not yet supported - dataActivityDirection = (activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel(), - carrierNetworkChangeActive = carrierNetworkChange, - resolvedNetworkType = dataType.toResolvedNetworkType() - ) - } - - private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel { - return createCarrierMergedConnectionModel( - this.level, - activity.toMobileDataActivityModel(), - ) - } - private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType { val key = mobileMappingsReverseLookup.value[this] ?: "dis" return DefaultNetworkType(key) @@ -364,8 +330,6 @@ constructor( private const val TAG = "DemoMobileConnectionsRepo" private const val DEFAULT_SUB_ID = 1 - - private const val CARRIER_MERGED_NAME = "Carrier Merged Network" } } @@ -379,13 +343,107 @@ class DemoMobileConnectionRepository( override val subId: Int, override val tableLogBuffer: TableLogBuffer, ) : MobileConnectionRepository { - override val connectionInfo = MutableStateFlow(MobileConnectionModel()) + private val _isEmergencyOnly = MutableStateFlow(false) + override val isEmergencyOnly = _isEmergencyOnly.asStateFlow() - override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS) + private val _isRoaming = MutableStateFlow(false) + override val isRoaming = _isRoaming.asStateFlow() + + private val _operatorAlphaShort: MutableStateFlow = MutableStateFlow(null) + override val operatorAlphaShort = _operatorAlphaShort.asStateFlow() + + private val _isInService = MutableStateFlow(false) + override val isInService = _isInService.asStateFlow() + + private val _isGsm = MutableStateFlow(false) + override val isGsm = _isGsm.asStateFlow() + + private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + override val cdmaLevel = _cdmaLevel.asStateFlow() + + private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + override val primaryLevel = _primaryLevel.asStateFlow() + + private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected) + override val dataConnectionState = _dataConnectionState.asStateFlow() + + private val _dataActivityDirection = + MutableStateFlow( + DataActivityModel( + hasActivityIn = false, + hasActivityOut = false, + ) + ) + override val dataActivityDirection = _dataActivityDirection.asStateFlow() + + private val _carrierNetworkChangeActive = MutableStateFlow(false) + override val carrierNetworkChangeActive = _carrierNetworkChangeActive.asStateFlow() + + private val _resolvedNetworkType: MutableStateFlow = + MutableStateFlow(ResolvedNetworkType.UnknownNetworkType) + override val resolvedNetworkType = _resolvedNetworkType.asStateFlow() + + override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS) override val dataEnabled = MutableStateFlow(true) override val cdmaRoaming = MutableStateFlow(false) override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network")) + + /** + * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately + * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level + * repository. + */ + fun processDemoMobileEvent( + event: FakeNetworkEventModel.Mobile, + resolvedNetworkType: ResolvedNetworkType, + ) { + // This is always true here, because we split out disabled states at the data-source level + dataEnabled.value = true + networkName.value = NetworkNameModel.IntentDerived(event.name) + + cdmaRoaming.value = event.roaming + _isRoaming.value = event.roaming + // TODO(b/261029387): not yet supported + _isEmergencyOnly.value = false + _operatorAlphaShort.value = event.name + _isInService.value = (event.level ?: 0) > 0 + // TODO(b/261029387): not yet supported + _isGsm.value = false + _cdmaLevel.value = event.level ?: 0 + _primaryLevel.value = event.level ?: 0 + // TODO(b/261029387): not yet supported + _dataConnectionState.value = DataConnectionState.Connected + _dataActivityDirection.value = + (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel() + _carrierNetworkChangeActive.value = event.carrierNetworkChange + _resolvedNetworkType.value = resolvedNetworkType + } + + fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) { + // 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) + numberOfLevels.value = event.numberOfLevels + cdmaRoaming.value = false + _primaryLevel.value = event.level + _cdmaLevel.value = event.level + _dataActivityDirection.value = event.activity.toMobileDataActivityModel() + + // These fields are always the same for carrier-merged networks + _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType + _dataConnectionState.value = DataConnectionState.Connected + _isRoaming.value = false + _isEmergencyOnly.value = false + _operatorAlphaShort.value = null + _isInService.value = true + _isGsm.value = false + _carrierNetworkChangeActive.value = false + } + + companion object { + private const val CARRIER_MERGED_NAME = "Carrier Merged Network" + } } 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 8f6a87b089f26..94d6d0b1db44a 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 @@ -16,18 +16,17 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod +import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN import android.telephony.TelephonyManager import android.util.Log import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application 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.MobileConnectionModel 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.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS -import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject @@ -94,16 +93,6 @@ class CarrierMergedConnectionRepository( } } - override val connectionInfo: StateFlow = - combine(network, wifiRepository.wifiActivity) { network, activity -> - if (network == null) { - MobileConnectionModel() - } else { - createCarrierMergedConnectionModel(network.level, activity) - } - } - .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel()) - override val cdmaRoaming: StateFlow = MutableStateFlow(ROAMING).asStateFlow() override val networkName: StateFlow = @@ -129,34 +118,54 @@ class CarrierMergedConnectionRepository( } .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS) + override val primaryLevel = + network + .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN } + .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + + override val cdmaLevel = + network + .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN } + .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + + override val dataActivityDirection = wifiRepository.wifiActivity + + override val resolvedNetworkType = + network + .map { + if (it != null) { + ResolvedNetworkType.CarrierMergedNetworkType + } else { + ResolvedNetworkType.UnknownNetworkType + } + } + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + ResolvedNetworkType.UnknownNetworkType + ) + + override val dataConnectionState = + network + .map { + if (it != null) { + DataConnectionState.Connected + } else { + DataConnectionState.Disconnected + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), DataConnectionState.Disconnected) + + override val isRoaming = MutableStateFlow(false).asStateFlow() + override val isEmergencyOnly = MutableStateFlow(false).asStateFlow() + override val operatorAlphaShort = MutableStateFlow(null).asStateFlow() + override val isInService = MutableStateFlow(true).asStateFlow() + override val isGsm = MutableStateFlow(false).asStateFlow() + override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow() + override val dataEnabled: StateFlow = wifiRepository.isWifiEnabled companion object { - /** - * Creates an instance of [MobileConnectionModel] that represents a carrier merged network - * with the given [level] and [activity]. - */ - fun createCarrierMergedConnectionModel( - level: Int, - activity: DataActivityModel, - ): MobileConnectionModel { - return MobileConnectionModel( - primaryLevel = level, - cdmaLevel = level, - dataActivityDirection = activity, - // Here and below: These values are always the same for every carrier-merged - // connection. - resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType, - dataConnectionState = DataConnectionState.Connected, - isRoaming = ROAMING, - isEmergencyOnly = false, - operatorAlphaShort = null, - isInService = true, - isGsm = false, - carrierNetworkChangeActive = false, - ) - } - // Carrier merged is never roaming private const val ROAMING = false } 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 a39ea0abce5ad..b3737ecd1e0bc 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 @@ -114,15 +114,147 @@ class FullMobileConnectionRepository( .flatMapLatest { it.cdmaRoaming } .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaRoaming.value) - override val connectionInfo = + override val isEmergencyOnly = activeRepo - .flatMapLatest { it.connectionInfo } + .flatMapLatest { it.isEmergencyOnly } .logDiffsForTable( tableLogBuffer, columnPrefix = "", - initialValue = activeRepo.value.connectionInfo.value, + columnName = COL_EMERGENCY, + activeRepo.value.isEmergencyOnly.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.isEmergencyOnly.value + ) + + override val isRoaming = + activeRepo + .flatMapLatest { it.isRoaming } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_ROAMING, + activeRepo.value.isRoaming.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value) + + override val operatorAlphaShort = + activeRepo + .flatMapLatest { it.operatorAlphaShort } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_OPERATOR, + activeRepo.value.operatorAlphaShort.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.operatorAlphaShort.value + ) + + override val isInService = + activeRepo + .flatMapLatest { it.isInService } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_IN_SERVICE, + activeRepo.value.isInService.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value) + + override val isGsm = + activeRepo + .flatMapLatest { it.isGsm } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_GSM, + activeRepo.value.isGsm.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value) + + override val cdmaLevel = + activeRepo + .flatMapLatest { it.cdmaLevel } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_CDMA_LEVEL, + activeRepo.value.cdmaLevel.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value) + + override val primaryLevel = + activeRepo + .flatMapLatest { it.primaryLevel } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_PRIMARY_LEVEL, + activeRepo.value.primaryLevel.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value) + + override val dataConnectionState = + activeRepo + .flatMapLatest { it.dataConnectionState } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + activeRepo.value.dataConnectionState.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.dataConnectionState.value + ) + + override val dataActivityDirection = + activeRepo + .flatMapLatest { it.dataActivityDirection } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + activeRepo.value.dataActivityDirection.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.dataActivityDirection.value + ) + + override val carrierNetworkChangeActive = + activeRepo + .flatMapLatest { it.carrierNetworkChangeActive } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_CARRIER_NETWORK_CHANGE, + activeRepo.value.carrierNetworkChangeActive.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.carrierNetworkChangeActive.value + ) + + override val resolvedNetworkType = + activeRepo + .flatMapLatest { it.resolvedNetworkType } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + activeRepo.value.resolvedNetworkType.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.resolvedNetworkType.value ) - .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value) override val dataEnabled = activeRepo @@ -187,4 +319,15 @@ class FullMobileConnectionRepository( fun tableBufferLogName(subId: Int): String = "MobileConnectionLog[$subId]" } } + + 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_NETWORK_CHANGE = "carrierNetworkChangeActive" + } } 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 e182bc66081aa..f1fc3868d6906 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 @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod import android.content.Context import android.content.IntentFilter import android.telephony.CellSignalStrength +import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN import android.telephony.CellSignalStrengthCdma import android.telephony.ServiceState import android.telephony.SignalStrength @@ -37,7 +38,7 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType @@ -49,6 +50,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierCon import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy +import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -62,10 +64,10 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapNotNull -import kotlinx.coroutines.flow.scan import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn @@ -165,83 +167,100 @@ class MobileConnectionRepositoryImpl( } .shareIn(scope, SharingStarted.WhileSubscribed()) - private fun updateConnectionState( - prevState: MobileConnectionModel, - callbackEvent: CallbackEvent, - ): MobileConnectionModel = - when (callbackEvent) { - is CallbackEvent.OnServiceStateChanged -> { - val serviceState = callbackEvent.serviceState - prevState.copy( - isEmergencyOnly = serviceState.isEmergencyOnly, - isRoaming = serviceState.roaming, - operatorAlphaShort = serviceState.operatorAlphaShort, - isInService = Utils.isInService(serviceState), - ) - } - is CallbackEvent.OnSignalStrengthChanged -> { - val signalStrength = callbackEvent.signalStrength - val cdmaLevel = - signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let { - strengths -> - if (!strengths.isEmpty()) { - strengths[0].level - } else { - CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN - } - } - - val primaryLevel = signalStrength.level - - prevState.copy( - cdmaLevel = cdmaLevel, - primaryLevel = primaryLevel, - isGsm = signalStrength.isGsm, - ) - } - is CallbackEvent.OnDataConnectionStateChanged -> { - prevState.copy(dataConnectionState = callbackEvent.dataState.toDataConnectionType()) - } - is CallbackEvent.OnDataActivity -> { - prevState.copy( - dataActivityDirection = callbackEvent.direction.toMobileDataActivityModel() - ) - } - is CallbackEvent.OnCarrierNetworkChange -> { - prevState.copy(carrierNetworkChangeActive = callbackEvent.active) - } - is CallbackEvent.OnDisplayInfoChanged -> { - val telephonyDisplayInfo = callbackEvent.telephonyDisplayInfo - val networkType = - if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) { - UnknownNetworkType - } else if ( - telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE - ) { - DefaultNetworkType( - mobileMappingsProxy.toIconKey(telephonyDisplayInfo.networkType) - ) - } else { - OverrideNetworkType( - mobileMappingsProxy.toIconKeyOverride( - telephonyDisplayInfo.overrideNetworkType - ) - ) - } - prevState.copy(resolvedNetworkType = networkType) - } - is CallbackEvent.OnDataEnabledChanged -> { - // Not part of this object, handled in a separate flow - prevState - } - } - - override val connectionInfo = run { - val initial = MobileConnectionModel() + override val isEmergencyOnly = callbackEvents - .scan(initial, ::updateConnectionState) - .stateIn(scope, SharingStarted.WhileSubscribed(), initial) - } + .filterIsInstance() + .map { it.serviceState.isEmergencyOnly } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + override val isRoaming = + callbackEvents + .filterIsInstance() + .map { it.serviceState.roaming } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + override val operatorAlphaShort = + callbackEvents + .filterIsInstance() + .map { it.serviceState.operatorAlphaShort } + .stateIn(scope, SharingStarted.WhileSubscribed(), null) + + override val isInService = + callbackEvents + .filterIsInstance() + .map { Utils.isInService(it.serviceState) } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + override val isGsm = + callbackEvents + .filterIsInstance() + .map { it.signalStrength.isGsm } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + override val cdmaLevel = + callbackEvents + .filterIsInstance() + .map { + it.signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let { + strengths -> + if (strengths.isNotEmpty()) { + strengths[0].level + } else { + CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN + } + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + + override val primaryLevel = + callbackEvents + .filterIsInstance() + .map { it.signalStrength.level } + .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + + override val dataConnectionState = + callbackEvents + .filterIsInstance() + .map { it.dataState.toDataConnectionType() } + .stateIn(scope, SharingStarted.WhileSubscribed(), Disconnected) + + override val dataActivityDirection = + callbackEvents + .filterIsInstance() + .map { it.direction.toMobileDataActivityModel() } + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + DataActivityModel(hasActivityIn = false, hasActivityOut = false) + ) + + override val carrierNetworkChangeActive = + callbackEvents + .filterIsInstance() + .map { it.active } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + override val resolvedNetworkType = + callbackEvents + .filterIsInstance() + .map { + if (it.telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) { + UnknownNetworkType + } else if ( + it.telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE + ) { + DefaultNetworkType( + mobileMappingsProxy.toIconKey(it.telephonyDisplayInfo.networkType) + ) + } else { + OverrideNetworkType( + mobileMappingsProxy.toIconKeyOverride( + it.telephonyDisplayInfo.overrideNetworkType + ) + ) + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType) override val numberOfLevels = systemUiCarrierConfig.shouldInflateSignalStrength 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 4caf2b09a3f2f..7df6764fda1a2 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 @@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.SharingStarted 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.onEach import kotlinx.coroutines.flow.stateIn @@ -133,11 +134,9 @@ class MobileIconInteractorImpl( override val isForceHidden: Flow, connectionRepository: MobileConnectionRepository, ) : MobileIconInteractor { - private val connectionInfo = connectionRepository.connectionInfo - override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer - override val activity = connectionInfo.mapLatest { it.dataActivityDirection } + override val activity = connectionRepository.dataActivityDirection override val isConnected: Flow = defaultMobileConnectivity.mapLatest { it.isConnected } @@ -155,11 +154,11 @@ class MobileIconInteractorImpl( override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled override val networkName = - combine(connectionInfo, connectionRepository.networkName) { connection, networkName -> - if ( - networkName is NetworkNameModel.Default && connection.operatorAlphaShort != null - ) { - NetworkNameModel.IntentDerived(connection.operatorAlphaShort) + combine(connectionRepository.operatorAlphaShort, connectionRepository.networkName) { + operatorAlphaShort, + networkName -> + if (networkName is NetworkNameModel.Default && operatorAlphaShort != null) { + NetworkNameModel.IntentDerived(operatorAlphaShort) } else { networkName } @@ -173,19 +172,19 @@ class MobileIconInteractorImpl( /** Observable for the current RAT indicator icon ([MobileIconGroup]) */ override val networkTypeIconGroup: StateFlow = combine( - connectionInfo, + connectionRepository.resolvedNetworkType, defaultMobileIconMapping, defaultMobileIconGroup, isDefault, - ) { info, mapping, defaultGroup, isDefault -> + ) { resolvedNetworkType, mapping, defaultGroup, isDefault -> if (!isDefault) { return@combine NOT_DEFAULT_DATA } - when (info.resolvedNetworkType) { + when (resolvedNetworkType) { is ResolvedNetworkType.CarrierMergedNetworkType -> - info.resolvedNetworkType.iconGroupOverride - else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup + resolvedNetworkType.iconGroupOverride + else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup } } .distinctUntilChanged() @@ -200,17 +199,19 @@ class MobileIconInteractorImpl( } .stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value) - override val isEmergencyOnly: StateFlow = - connectionInfo - .mapLatest { it.isEmergencyOnly } - .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isEmergencyOnly = connectionRepository.isEmergencyOnly override val isRoaming: StateFlow = - combine(connectionInfo, connectionRepository.cdmaRoaming) { connection, cdmaRoaming -> - if (connection.carrierNetworkChangeActive) { + combine( + connectionRepository.carrierNetworkChangeActive, + connectionRepository.isGsm, + connectionRepository.isRoaming, + connectionRepository.cdmaRoaming, + ) { carrierNetworkChangeActive, isGsm, isRoaming, cdmaRoaming -> + if (carrierNetworkChangeActive) { false - } else if (connection.isGsm) { - connection.isRoaming + } else if (isGsm) { + isRoaming } else { cdmaRoaming } @@ -218,12 +219,17 @@ class MobileIconInteractorImpl( .stateIn(scope, SharingStarted.WhileSubscribed(), false) override val level: StateFlow = - combine(connectionInfo, alwaysUseCdmaLevel) { connection, alwaysUseCdmaLevel -> + combine( + connectionRepository.isGsm, + connectionRepository.primaryLevel, + connectionRepository.cdmaLevel, + alwaysUseCdmaLevel, + ) { isGsm, primaryLevel, cdmaLevel, alwaysUseCdmaLevel -> when { // GSM connections should never use the CDMA level - connection.isGsm -> connection.primaryLevel - alwaysUseCdmaLevel -> connection.cdmaLevel - else -> connection.primaryLevel + isGsm -> primaryLevel + alwaysUseCdmaLevel -> cdmaLevel + else -> primaryLevel } } .stateIn(scope, SharingStarted.WhileSubscribed(), 0) @@ -236,12 +242,9 @@ class MobileIconInteractorImpl( ) override val isDataConnected: StateFlow = - connectionInfo - .mapLatest { connection -> connection.dataConnectionState == Connected } + connectionRepository.dataConnectionState + .map { it == Connected } .stateIn(scope, SharingStarted.WhileSubscribed(), false) - override val isInService = - connectionRepository.connectionInfo - .mapLatest { it.isInService } - .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isInService = connectionRepository.isInService } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt deleted file mode 100644 index 45189cf8d432f..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2022 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.data.model - -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.log.table.TableRowLogger -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_IN -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_OUT -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_IS_GSM -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_RESOLVED_NETWORK_TYPE -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ROAMING -import com.google.common.truth.Truth.assertThat -import org.junit.Test - -@SmallTest -class MobileConnectionModelTest : SysuiTestCase() { - - @Test - fun `log diff - initial log contains all columns`() { - val logger = TestLogger() - val connection = MobileConnectionModel() - - connection.logFull(logger) - - assertThat(logger.changes) - .contains(Pair(COL_EMERGENCY, connection.isEmergencyOnly.toString())) - assertThat(logger.changes).contains(Pair(COL_ROAMING, connection.isRoaming.toString())) - assertThat(logger.changes) - .contains(Pair(COL_OPERATOR, connection.operatorAlphaShort.toString())) - assertThat(logger.changes).contains(Pair(COL_IS_GSM, connection.isGsm.toString())) - assertThat(logger.changes).contains(Pair(COL_CDMA_LEVEL, connection.cdmaLevel.toString())) - assertThat(logger.changes) - .contains(Pair(COL_PRIMARY_LEVEL, connection.primaryLevel.toString())) - assertThat(logger.changes) - .contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString())) - assertThat(logger.changes) - .contains( - Pair( - COL_ACTIVITY_DIRECTION_IN, - connection.dataActivityDirection.hasActivityIn.toString(), - ) - ) - assertThat(logger.changes) - .contains( - Pair( - COL_ACTIVITY_DIRECTION_OUT, - connection.dataActivityDirection.hasActivityOut.toString(), - ) - ) - assertThat(logger.changes) - .contains( - Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString()) - ) - assertThat(logger.changes) - .contains(Pair(COL_RESOLVED_NETWORK_TYPE, connection.resolvedNetworkType.toString())) - } - - @Test - fun `log diff - primary level changes - only level is logged`() { - val logger = TestLogger() - val connectionOld = MobileConnectionModel(primaryLevel = 1) - - val connectionNew = MobileConnectionModel(primaryLevel = 2) - - connectionNew.logDiffs(connectionOld, logger) - - assertThat(logger.changes).isEqualTo(listOf(Pair(COL_PRIMARY_LEVEL, "2"))) - } - - private class TestLogger : TableRowLogger { - val changes = mutableListOf>() - - override fun logChange(columnName: String, value: String?) { - changes.add(Pair(columnName, value.toString())) - } - - override fun logChange(columnName: String, value: Int) { - changes.add(Pair(columnName, value.toString())) - } - - override fun logChange(columnName: String, value: Boolean) { - changes.add(Pair(columnName, value.toString())) - } - } -} 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 53cd71f1bdf93..44fbd5b99894c 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 @@ -17,9 +17,11 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository import com.android.systemui.log.table.TableLogBuffer -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS +import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import kotlinx.coroutines.flow.MutableStateFlow // TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository @@ -27,8 +29,19 @@ class FakeMobileConnectionRepository( override val subId: Int, override val tableLogBuffer: TableLogBuffer, ) : MobileConnectionRepository { - private val _connectionInfo = MutableStateFlow(MobileConnectionModel()) - override val connectionInfo = _connectionInfo + override val isEmergencyOnly = MutableStateFlow(false) + override val isRoaming = MutableStateFlow(false) + override val operatorAlphaShort: MutableStateFlow = MutableStateFlow(null) + override val isInService = MutableStateFlow(false) + override val isGsm = MutableStateFlow(false) + override val cdmaLevel = MutableStateFlow(0) + override val primaryLevel = MutableStateFlow(0) + override val dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected) + override val dataActivityDirection = + MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false)) + override val carrierNetworkChangeActive = MutableStateFlow(false) + override val resolvedNetworkType: MutableStateFlow = + MutableStateFlow(ResolvedNetworkType.UnknownNetworkType) override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS) @@ -40,10 +53,6 @@ class FakeMobileConnectionRepository( override val networkName = MutableStateFlow(NetworkNameModel.Default("default")) - fun setConnectionInfo(model: MobileConnectionModel) { - _connectionInfo.value = model - } - fun setDataEnabled(enabled: Boolean) { _dataEnabled.value = enabled } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index b072deedb9c98..4a2dce4f7965b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -25,7 +25,6 @@ import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel @@ -129,23 +128,21 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC ) { when (model) { is FakeNetworkEventModel.Mobile -> { - val connectionInfo: MobileConnectionModel = conn.connectionInfo.value assertThat(conn.subId).isEqualTo(model.subId) - assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level) - assertThat(connectionInfo.primaryLevel).isEqualTo(model.level) - assertThat(connectionInfo.dataActivityDirection) + assertThat(conn.cdmaLevel.value).isEqualTo(model.level) + assertThat(conn.primaryLevel.value).isEqualTo(model.level) + assertThat(conn.dataActivityDirection.value) .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel()) - assertThat(connectionInfo.carrierNetworkChangeActive) + assertThat(conn.carrierNetworkChangeActive.value) .isEqualTo(model.carrierNetworkChange) - assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming) + assertThat(conn.isRoaming.value).isEqualTo(model.roaming) assertThat(conn.networkName.value) .isEqualTo(NetworkNameModel.IntentDerived(model.name)) // TODO(b/261029387): check these once we start handling them - assertThat(connectionInfo.isEmergencyOnly).isFalse() - assertThat(connectionInfo.isGsm).isFalse() - assertThat(connectionInfo.dataConnectionState) - .isEqualTo(DataConnectionState.Connected) + assertThat(conn.isEmergencyOnly.value).isFalse() + assertThat(conn.isGsm.value).isFalse() + assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected) } // MobileDisabled isn't combinatorial in nature, and is tested in // DemoMobileConnectionsRepositoryTest.kt diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index f60d92bde202d..c8b1d3021c42b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.log.table.TableLogBufferFactory import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel @@ -526,27 +525,25 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { private fun assertConnection( conn: DemoMobileConnectionRepository, - model: FakeNetworkEventModel + model: FakeNetworkEventModel, ) { when (model) { is FakeNetworkEventModel.Mobile -> { - val connectionInfo: MobileConnectionModel = conn.connectionInfo.value assertThat(conn.subId).isEqualTo(model.subId) - assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level) - assertThat(connectionInfo.primaryLevel).isEqualTo(model.level) - assertThat(connectionInfo.dataActivityDirection) + assertThat(conn.cdmaLevel.value).isEqualTo(model.level) + assertThat(conn.primaryLevel.value).isEqualTo(model.level) + assertThat(conn.dataActivityDirection.value) .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel()) - assertThat(connectionInfo.carrierNetworkChangeActive) + assertThat(conn.carrierNetworkChangeActive.value) .isEqualTo(model.carrierNetworkChange) - assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming) + assertThat(conn.isRoaming.value).isEqualTo(model.roaming) assertThat(conn.networkName.value) .isEqualTo(NetworkNameModel.IntentDerived(model.name)) // TODO(b/261029387) check these once we start handling them - assertThat(connectionInfo.isEmergencyOnly).isFalse() - assertThat(connectionInfo.isGsm).isFalse() - assertThat(connectionInfo.dataConnectionState) - .isEqualTo(DataConnectionState.Connected) + assertThat(conn.isEmergencyOnly.value).isFalse() + assertThat(conn.isGsm.value).isFalse() + assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected) } else -> {} } @@ -556,15 +553,14 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { conn: DemoMobileConnectionRepository, model: FakeWifiEventModel.CarrierMerged, ) { - val connectionInfo: MobileConnectionModel = conn.connectionInfo.value assertThat(conn.subId).isEqualTo(model.subscriptionId) - assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level) - assertThat(connectionInfo.primaryLevel).isEqualTo(model.level) - assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false) - assertThat(connectionInfo.isRoaming).isEqualTo(false) - assertThat(connectionInfo.isEmergencyOnly).isFalse() - assertThat(connectionInfo.isGsm).isFalse() - assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected) + assertThat(conn.cdmaLevel.value).isEqualTo(model.level) + assertThat(conn.primaryLevel.value).isEqualTo(model.level) + assertThat(conn.carrierNetworkChangeActive.value).isEqualTo(false) + assertThat(conn.isRoaming.value).isEqualTo(false) + assertThat(conn.isEmergencyOnly.value).isFalse() + assertThat(conn.isGsm.value).isFalse() + assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt index f0f213bc0d584..441186acb6b77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase 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.MobileConnectionModel 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.shared.data.model.DataActivityModel @@ -75,36 +74,48 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { } @Test - fun connectionInfo_inactiveWifi_isDefault() = + fun inactiveWifi_isDefault() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestConnState: DataConnectionState? = null + var latestNetType: ResolvedNetworkType? = null + + val dataJob = + underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this) + val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this) wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) - assertThat(latest).isEqualTo(MobileConnectionModel()) + assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected) + assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType) - job.cancel() + dataJob.cancel() + netJob.cancel() } @Test - fun connectionInfo_activeWifi_isDefault() = + fun activeWifi_isDefault() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestConnState: DataConnectionState? = null + var latestNetType: ResolvedNetworkType? = null + + val dataJob = + underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this) + val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this) wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1)) - assertThat(latest).isEqualTo(MobileConnectionModel()) + assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected) + assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType) - job.cancel() + dataJob.cancel() + netJob.cancel() } @Test - fun connectionInfo_carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() = + fun carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Int? = null + val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this) wifiRepository.setIsWifiEnabled(true) wifiRepository.setIsWifiDefault(true) @@ -117,34 +128,16 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) ) - val expected = - MobileConnectionModel( - primaryLevel = 3, - cdmaLevel = 3, - dataConnectionState = DataConnectionState.Connected, - dataActivityDirection = - DataActivityModel( - hasActivityIn = false, - hasActivityOut = false, - ), - resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType, - isRoaming = false, - isEmergencyOnly = false, - operatorAlphaShort = null, - isInService = true, - isGsm = false, - carrierNetworkChangeActive = false, - ) - assertThat(latest).isEqualTo(expected) + assertThat(latest).isEqualTo(3) job.cancel() } @Test - fun connectionInfo_activity_comesFromWifiActivity() = + fun activity_comesFromWifiActivity() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataActivityModel? = null + val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this) wifiRepository.setIsWifiEnabled(true) wifiRepository.setIsWifiDefault(true) @@ -162,8 +155,8 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) ) - assertThat(latest!!.dataActivityDirection.hasActivityIn).isTrue() - assertThat(latest!!.dataActivityDirection.hasActivityOut).isFalse() + assertThat(latest!!.hasActivityIn).isTrue() + assertThat(latest!!.hasActivityOut).isFalse() wifiRepository.setWifiActivity( DataActivityModel( @@ -172,17 +165,19 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) ) - assertThat(latest!!.dataActivityDirection.hasActivityIn).isFalse() - assertThat(latest!!.dataActivityDirection.hasActivityOut).isTrue() + assertThat(latest!!.hasActivityIn).isFalse() + assertThat(latest!!.hasActivityOut).isTrue() job.cancel() } @Test - fun connectionInfo_carrierMergedWifi_wrongSubId_isDefault() = + fun carrierMergedWifi_wrongSubId_isDefault() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestLevel: Int? = null + var latestType: ResolvedNetworkType? = null + val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this) + val typeJob = underTest.resolvedNetworkType.onEach { latestType = it }.launchIn(this) wifiRepository.setWifiNetwork( WifiNetworkModel.CarrierMerged( @@ -192,20 +187,19 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) ) - assertThat(latest).isEqualTo(MobileConnectionModel()) - assertThat(latest!!.primaryLevel).isNotEqualTo(3) - assertThat(latest!!.resolvedNetworkType) - .isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType) + assertThat(latestLevel).isNotEqualTo(3) + assertThat(latestType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType) - job.cancel() + levelJob.cancel() + typeJob.cancel() } // This scenario likely isn't possible, but write a test for it anyway @Test - fun connectionInfo_carrierMergedButNotEnabled_isDefault() = + fun carrierMergedButNotEnabled_isDefault() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Int? = null + val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this) wifiRepository.setWifiNetwork( WifiNetworkModel.CarrierMerged( @@ -216,17 +210,17 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) wifiRepository.setIsWifiEnabled(false) - assertThat(latest).isEqualTo(MobileConnectionModel()) + assertThat(latest).isNotEqualTo(3) job.cancel() } // This scenario likely isn't possible, but write a test for it anyway @Test - fun connectionInfo_carrierMergedButWifiNotDefault_isDefault() = + fun carrierMergedButWifiNotDefault_isDefault() = testScope.runTest { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Int? = null + val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this) wifiRepository.setWifiNetwork( WifiNetworkModel.CarrierMerged( @@ -237,7 +231,7 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() { ) wifiRepository.setIsWifiDefault(false) - assertThat(latest).isEqualTo(MobileConnectionModel()) + assertThat(latest).isNotEqualTo(3) job.cancel() } 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 cd4d8472763f2..db5a7d1ad84a5 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 @@ -24,13 +24,12 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel @@ -94,16 +93,16 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { @Test fun startingIsCarrierMerged_usesCarrierMergedInitially() = testScope.runTest { - val carrierMergedConnectionInfo = - MobileConnectionModel( - operatorAlphaShort = "Carrier Merged Operator", - ) - carrierMergedRepo.setConnectionInfo(carrierMergedConnectionInfo) + val carrierMergedOperatorName = "Carrier Merged Operator" + val nonCarrierMergedName = "Non-carrier-merged" + + carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName + mobileRepo.operatorAlphaShort.value = nonCarrierMergedName initializeRepo(startingIsCarrierMerged = true) assertThat(underTest.activeRepo.value).isEqualTo(carrierMergedRepo) - assertThat(underTest.connectionInfo.value).isEqualTo(carrierMergedConnectionInfo) + assertThat(underTest.operatorAlphaShort.value).isEqualTo(carrierMergedOperatorName) verify(mobileFactory, never()) .build( SUB_ID, @@ -116,16 +115,16 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { @Test fun startingNotCarrierMerged_usesTypicalInitially() = testScope.runTest { - val mobileConnectionInfo = - MobileConnectionModel( - operatorAlphaShort = "Typical Operator", - ) - mobileRepo.setConnectionInfo(mobileConnectionInfo) + val carrierMergedOperatorName = "Carrier Merged Operator" + val nonCarrierMergedName = "Typical Operator" + + carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName + mobileRepo.operatorAlphaShort.value = nonCarrierMergedName initializeRepo(startingIsCarrierMerged = false) assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo) - assertThat(underTest.connectionInfo.value).isEqualTo(mobileConnectionInfo) + assertThat(underTest.operatorAlphaShort.value).isEqualTo(nonCarrierMergedName) verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer) } @@ -156,39 +155,40 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { testScope.runTest { initializeRepo(startingIsCarrierMerged = false) - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestName: String? = null + var latestLevel: Int? = null + + val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this) + val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this) underTest.setIsCarrierMerged(true) - val info1 = - MobileConnectionModel( - operatorAlphaShort = "Carrier Merged Operator", - primaryLevel = 1, - ) - carrierMergedRepo.setConnectionInfo(info1) + val operator1 = "Carrier Merged Operator" + val level1 = 1 + carrierMergedRepo.operatorAlphaShort.value = operator1 + carrierMergedRepo.primaryLevel.value = level1 - assertThat(latest).isEqualTo(info1) + assertThat(latestName).isEqualTo(operator1) + assertThat(latestLevel).isEqualTo(level1) - val info2 = - MobileConnectionModel( - operatorAlphaShort = "Carrier Merged Operator #2", - primaryLevel = 2, - ) - carrierMergedRepo.setConnectionInfo(info2) + val operator2 = "Carrier Merged Operator #2" + val level2 = 2 + carrierMergedRepo.operatorAlphaShort.value = operator2 + carrierMergedRepo.primaryLevel.value = level2 - assertThat(latest).isEqualTo(info2) + assertThat(latestName).isEqualTo(operator2) + assertThat(latestLevel).isEqualTo(level2) - val info3 = - MobileConnectionModel( - operatorAlphaShort = "Carrier Merged Operator #3", - primaryLevel = 3, - ) - carrierMergedRepo.setConnectionInfo(info3) + val operator3 = "Carrier Merged Operator #3" + val level3 = 3 + carrierMergedRepo.operatorAlphaShort.value = operator3 + carrierMergedRepo.primaryLevel.value = level3 - assertThat(latest).isEqualTo(info3) + assertThat(latestName).isEqualTo(operator3) + assertThat(latestLevel).isEqualTo(level3) - job.cancel() + nameJob.cancel() + levelJob.cancel() } @Test @@ -196,39 +196,40 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { testScope.runTest { initializeRepo(startingIsCarrierMerged = false) - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestName: String? = null + var latestLevel: Int? = null + + val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this) + val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this) underTest.setIsCarrierMerged(false) - val info1 = - MobileConnectionModel( - operatorAlphaShort = "Typical Merged Operator", - primaryLevel = 1, - ) - mobileRepo.setConnectionInfo(info1) + val operator1 = "Typical Merged Operator" + val level1 = 1 + mobileRepo.operatorAlphaShort.value = operator1 + mobileRepo.primaryLevel.value = level1 - assertThat(latest).isEqualTo(info1) + assertThat(latestName).isEqualTo(operator1) + assertThat(latestLevel).isEqualTo(level1) - val info2 = - MobileConnectionModel( - operatorAlphaShort = "Typical Merged Operator #2", - primaryLevel = 2, - ) - mobileRepo.setConnectionInfo(info2) + val operator2 = "Typical Merged Operator #2" + val level2 = 2 + mobileRepo.operatorAlphaShort.value = operator2 + mobileRepo.primaryLevel.value = level2 - assertThat(latest).isEqualTo(info2) + assertThat(latestName).isEqualTo(operator2) + assertThat(latestLevel).isEqualTo(level2) - val info3 = - MobileConnectionModel( - operatorAlphaShort = "Typical Merged Operator #3", - primaryLevel = 3, - ) - mobileRepo.setConnectionInfo(info3) + val operator3 = "Typical Merged Operator #3" + val level3 = 3 + mobileRepo.operatorAlphaShort.value = operator3 + mobileRepo.primaryLevel.value = level3 - assertThat(latest).isEqualTo(info3) + assertThat(latestName).isEqualTo(operator3) + assertThat(latestLevel).isEqualTo(level3) - job.cancel() + nameJob.cancel() + levelJob.cancel() } @Test @@ -236,57 +237,58 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { testScope.runTest { initializeRepo(startingIsCarrierMerged = false) - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latestName: String? = null + var latestLevel: Int? = null - val carrierMergedInfo = - MobileConnectionModel( - operatorAlphaShort = "Carrier Merged Operator", - primaryLevel = 4, - ) - carrierMergedRepo.setConnectionInfo(carrierMergedInfo) + val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this) + val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this) - val mobileInfo = - MobileConnectionModel( - operatorAlphaShort = "Typical Operator", - primaryLevel = 2, - ) - mobileRepo.setConnectionInfo(mobileInfo) + val carrierMergedOperator = "Carrier Merged Operator" + val carrierMergedLevel = 4 + carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperator + carrierMergedRepo.primaryLevel.value = carrierMergedLevel + + val mobileName = "Typical Operator" + val mobileLevel = 2 + mobileRepo.operatorAlphaShort.value = mobileName + mobileRepo.primaryLevel.value = mobileLevel // Start with the mobile info - assertThat(latest).isEqualTo(mobileInfo) + assertThat(latestName).isEqualTo(mobileName) + assertThat(latestLevel).isEqualTo(mobileLevel) // WHEN isCarrierMerged is set to true underTest.setIsCarrierMerged(true) // THEN the carrier merged info is used - assertThat(latest).isEqualTo(carrierMergedInfo) + assertThat(latestName).isEqualTo(carrierMergedOperator) + assertThat(latestLevel).isEqualTo(carrierMergedLevel) - val newCarrierMergedInfo = - MobileConnectionModel( - operatorAlphaShort = "New CM Operator", - primaryLevel = 0, - ) - carrierMergedRepo.setConnectionInfo(newCarrierMergedInfo) + val newCarrierMergedName = "New CM Operator" + val newCarrierMergedLevel = 0 + carrierMergedRepo.operatorAlphaShort.value = newCarrierMergedName + carrierMergedRepo.primaryLevel.value = newCarrierMergedLevel - assertThat(latest).isEqualTo(newCarrierMergedInfo) + assertThat(latestName).isEqualTo(newCarrierMergedName) + assertThat(latestLevel).isEqualTo(newCarrierMergedLevel) // WHEN isCarrierMerged is set to false underTest.setIsCarrierMerged(false) // THEN the typical info is used - assertThat(latest).isEqualTo(mobileInfo) + assertThat(latestName).isEqualTo(mobileName) + assertThat(latestLevel).isEqualTo(mobileLevel) - val newMobileInfo = - MobileConnectionModel( - operatorAlphaShort = "New Mobile Operator", - primaryLevel = 3, - ) - mobileRepo.setConnectionInfo(newMobileInfo) + val newMobileName = "New MobileOperator" + val newMobileLevel = 3 + mobileRepo.operatorAlphaShort.value = newMobileName + mobileRepo.primaryLevel.value = newMobileLevel - assertThat(latest).isEqualTo(newMobileInfo) + assertThat(latestName).isEqualTo(newMobileName) + assertThat(latestLevel).isEqualTo(newMobileLevel) - job.cancel() + nameJob.cancel() + levelJob.cancel() } @Test @@ -370,7 +372,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { initializeRepo(startingIsCarrierMerged = false) - val job = underTest.connectionInfo.launchIn(this) + val emergencyJob = underTest.isEmergencyOnly.launchIn(this) + val operatorJob = underTest.operatorAlphaShort.launchIn(this) // WHEN we set up some mobile connection info val serviceState = ServiceState() @@ -394,7 +397,8 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff") assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true") - job.cancel() + emergencyJob.cancel() + operatorJob.cancel() } @Test @@ -409,7 +413,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { initializeRepo(startingIsCarrierMerged = true) - val job = underTest.connectionInfo.launchIn(this) + val job = underTest.primaryLevel.launchIn(this) // WHEN we set up carrier merged info val networkId = 2 @@ -452,7 +456,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { initializeRepo(startingIsCarrierMerged = false) - val job = underTest.connectionInfo.launchIn(this) + val job = underTest.primaryLevel.launchIn(this) // WHEN we set up some mobile connection info val signalStrength = mock() @@ -502,12 +506,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { assertThat(bufferAfterCarrierMerged).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1") // WHEN the normal network is updated - val newMobileInfo = - MobileConnectionModel( - operatorAlphaShort = "Mobile Operator 2", - primaryLevel = 0, - ) - mobileRepo.setConnectionInfo(newMobileInfo) + mobileRepo.primaryLevel.value = 0 // THEN the new level is logged assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}0") @@ -529,7 +528,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { // WHEN isCarrierMerged = false initializeRepo(startingIsCarrierMerged = false) - val job = underTest.connectionInfo.launchIn(this) + val job = underTest.primaryLevel.launchIn(this) val signalStrength = mock() whenever(signalStrength.level).thenReturn(1) 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 bd5a4d7f7385f..abc722a94c852 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 @@ -55,8 +55,8 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType @@ -135,235 +135,267 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { } @Test - fun testFlowForSubId_default() = + fun emergencyOnly() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) - - assertThat(latest).isEqualTo(MobileConnectionModel()) - - job.cancel() - } - - @Test - fun testFlowForSubId_emergencyOnly() = - runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Boolean? = null + val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this) val serviceState = ServiceState() serviceState.isEmergencyOnly = true getTelephonyCallbackForType().onServiceStateChanged(serviceState) - assertThat(latest?.isEmergencyOnly).isEqualTo(true) + assertThat(latest).isEqualTo(true) job.cancel() } @Test - fun testFlowForSubId_emergencyOnly_toggles() = + fun emergencyOnly_toggles() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Boolean? = null + val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() val serviceState = ServiceState() serviceState.isEmergencyOnly = true callback.onServiceStateChanged(serviceState) + assertThat(latest).isTrue() + serviceState.isEmergencyOnly = false callback.onServiceStateChanged(serviceState) - assertThat(latest?.isEmergencyOnly).isEqualTo(false) + assertThat(latest).isFalse() job.cancel() } @Test - fun testFlowForSubId_signalStrengths_levelsUpdate() = + fun cdmaLevelUpdates() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Int? = null + val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() - val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true) + var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true) callback.onSignalStrengthsChanged(strength) - assertThat(latest?.isGsm).isEqualTo(true) - assertThat(latest?.primaryLevel).isEqualTo(1) - assertThat(latest?.cdmaLevel).isEqualTo(2) + assertThat(latest).isEqualTo(2) + + // gsmLevel updates, no change to cdmaLevel + strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true) + + assertThat(latest).isEqualTo(2) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_connected() = + fun gsmLevelUpdates() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Int? = null + val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this) + + val callback = getTelephonyCallbackForType() + var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true) + callback.onSignalStrengthsChanged(strength) + + assertThat(latest).isEqualTo(1) + + strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true) + callback.onSignalStrengthsChanged(strength) + + assertThat(latest).isEqualTo(3) + + job.cancel() + } + + @Test + fun isGsm() = + runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest.isGsm.onEach { latest = it }.launchIn(this) + + val callback = getTelephonyCallbackForType() + var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true) + callback.onSignalStrengthsChanged(strength) + + assertThat(latest).isTrue() + + strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = false) + callback.onSignalStrengthsChanged(strength) + + assertThat(latest).isFalse() + + job.cancel() + } + + @Test + fun dataConnectionState_connected() = + runBlocking(IMMEDIATE) { + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_CONNECTED, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connected) + assertThat(latest).isEqualTo(DataConnectionState.Connected) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_connecting() = + fun dataConnectionState_connecting() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_CONNECTING, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connecting) + assertThat(latest).isEqualTo(DataConnectionState.Connecting) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_disconnected() = + fun dataConnectionState_disconnected() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_DISCONNECTED, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnected) + assertThat(latest).isEqualTo(DataConnectionState.Disconnected) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_disconnecting() = + fun dataConnectionState_disconnecting() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_DISCONNECTING, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnecting) + assertThat(latest).isEqualTo(DataConnectionState.Disconnecting) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_suspended() = + fun dataConnectionState_suspended() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Suspended) + assertThat(latest).isEqualTo(DataConnectionState.Suspended) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_handoverInProgress() = + fun dataConnectionState_handoverInProgress() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */) - assertThat(latest?.dataConnectionState) - .isEqualTo(DataConnectionState.HandoverInProgress) + assertThat(latest).isEqualTo(DataConnectionState.HandoverInProgress) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_unknown() = + fun dataConnectionState_unknown() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(DATA_UNKNOWN, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Unknown) + assertThat(latest).isEqualTo(DataConnectionState.Unknown) job.cancel() } @Test - fun testFlowForSubId_dataConnectionState_invalid() = + fun dataConnectionState_invalid() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataConnectionState? = null + val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataConnectionStateChanged(45, 200 /* unused */) - assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Invalid) + assertThat(latest).isEqualTo(DataConnectionState.Invalid) job.cancel() } @Test - fun testFlowForSubId_dataActivity() = + fun dataActivity() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: DataActivityModel? = null + val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onDataActivity(DATA_ACTIVITY_INOUT) - assertThat(latest?.dataActivityDirection) - .isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel()) + assertThat(latest).isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel()) job.cancel() } @Test - fun testFlowForSubId_carrierNetworkChange() = + fun carrierNetworkChange() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: Boolean? = null + val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() callback.onCarrierNetworkChange(true) - assertThat(latest?.carrierNetworkChangeActive).isEqualTo(true) + assertThat(latest).isEqualTo(true) job.cancel() } @Test - fun subscriptionFlow_networkType_default() = + fun networkType_default() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: ResolvedNetworkType? = null + val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this) val expected = UnknownNetworkType - assertThat(latest?.resolvedNetworkType).isEqualTo(expected) + assertThat(latest).isEqualTo(expected) job.cancel() } @Test - fun subscriptionFlow_networkType_updatesUsingDefault() = + fun networkType_updatesUsingDefault() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: ResolvedNetworkType? = null + val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() val type = NETWORK_TYPE_LTE @@ -371,16 +403,16 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { val ti = mock().also { whenever(it.networkType).thenReturn(type) } callback.onDisplayInfoChanged(ti) - assertThat(latest?.resolvedNetworkType).isEqualTo(expected) + assertThat(latest).isEqualTo(expected) job.cancel() } @Test - fun subscriptionFlow_networkType_updatesUsingOverride() = + fun networkType_updatesUsingOverride() = runBlocking(IMMEDIATE) { - var latest: MobileConnectionModel? = null - val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this) + var latest: ResolvedNetworkType? = null + val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this) val callback = getTelephonyCallbackForType() val type = OVERRIDE_NETWORK_TYPE_LTE_CA @@ -392,7 +424,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { } callback.onDisplayInfoChanged(ti) - assertThat(latest?.resolvedNetworkType).isEqualTo(expected) + assertThat(latest).isEqualTo(expected) job.cancel() } @@ -466,7 +498,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { fun `roaming - gsm - queries service state`() = runBlocking(IMMEDIATE) { var latest: Boolean? = null - val job = underTest.connectionInfo.onEach { latest = it.isRoaming }.launchIn(this) + val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) val serviceState = ServiceState() serviceState.roaming = false @@ -492,8 +524,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { fun `activity - updates from callback`() = runBlocking(IMMEDIATE) { var latest: DataActivityModel? = null - val job = - underTest.connectionInfo.onEach { latest = it.dataActivityDirection }.launchIn(this) + val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this) assertThat(latest) .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false)) @@ -611,8 +642,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { runBlocking(IMMEDIATE) { var latest: String? = null - val job = - underTest.connectionInfo.onEach { latest = it.operatorAlphaShort }.launchIn(this) + val job = underTest.operatorAlphaShort.onEach { latest = it }.launchIn(this) val shortName = "short name" val serviceState = ServiceState() @@ -633,7 +663,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { fun `connection model - isInService - not iwlan`() = runBlocking(IMMEDIATE) { var latest: Boolean? = null - val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this) + val job = underTest.isInService.onEach { latest = it }.launchIn(this) val serviceState = ServiceState() serviceState.voiceRegState = STATE_IN_SERVICE @@ -658,7 +688,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { fun `connection model - isInService - is iwlan - voice out of service - data in service`() = runBlocking(IMMEDIATE) { var latest: Boolean? = null - val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this) + val job = underTest.isInService.onEach { latest = it }.launchIn(this) // Mock the service state here so we can make it specifically IWLAN val serviceState: ServiceState = mock() 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 fa072fc366eb3..1eb1056204cdf 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 @@ -23,7 +23,6 @@ import com.android.settingslib.SignalIcon.MobileIconGroup import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState -import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType @@ -74,9 +73,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun gsm_level_default_unknown() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel(isGsm = true), - ) + connectionRepository.isGsm.value = true var latest: Int? = null val job = underTest.level.onEach { latest = it }.launchIn(this) @@ -89,13 +86,9 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun gsm_usesGsmLevel() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = true, - primaryLevel = GSM_LEVEL, - cdmaLevel = CDMA_LEVEL - ), - ) + connectionRepository.isGsm.value = true + connectionRepository.primaryLevel.value = GSM_LEVEL + connectionRepository.cdmaLevel.value = CDMA_LEVEL var latest: Int? = null val job = underTest.level.onEach { latest = it }.launchIn(this) @@ -108,13 +101,9 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = true, - primaryLevel = GSM_LEVEL, - cdmaLevel = CDMA_LEVEL, - ), - ) + connectionRepository.isGsm.value = true + connectionRepository.primaryLevel.value = GSM_LEVEL + connectionRepository.cdmaLevel.value = CDMA_LEVEL mobileIconsInteractor.alwaysUseCdmaLevel.value = true var latest: Int? = null @@ -128,9 +117,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_level_default_unknown() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel(isGsm = false), - ) + connectionRepository.isGsm.value = false var latest: Int? = null val job = underTest.level.onEach { latest = it }.launchIn(this) @@ -142,13 +129,9 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = false, - primaryLevel = GSM_LEVEL, - cdmaLevel = CDMA_LEVEL - ), - ) + connectionRepository.isGsm.value = false + connectionRepository.primaryLevel.value = GSM_LEVEL + connectionRepository.cdmaLevel.value = CDMA_LEVEL mobileIconsInteractor.alwaysUseCdmaLevel.value = true var latest: Int? = null @@ -162,13 +145,9 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = false, - primaryLevel = GSM_LEVEL, - cdmaLevel = CDMA_LEVEL, - ), - ) + connectionRepository.isGsm.value = false + connectionRepository.primaryLevel.value = GSM_LEVEL + connectionRepository.cdmaLevel.value = CDMA_LEVEL mobileIconsInteractor.alwaysUseCdmaLevel.value = false var latest: Int? = null @@ -197,11 +176,8 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_three_g() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - ), - ) + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) @@ -214,23 +190,14 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_updates_on_change() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - ), - ) + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = - DefaultNetworkType( - mobileMappingsProxy.toIconKey(FOUR_G), - ), - ), - ) + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G)) yield() assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G) @@ -241,12 +208,8 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_5g_override_type() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = - OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE)) - ), - ) + connectionRepository.resolvedNetworkType.value = + OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE)) var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) @@ -259,12 +222,8 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_default_if_no_lookup() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = - DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)), - ), - ) + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)) var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) @@ -277,11 +236,7 @@ class MobileIconInteractorTest : SysuiTestCase() { @Test fun iconGroup_carrierMerged_usesOverride() = runBlocking(IMMEDIATE) { - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = CarrierMergedNetworkType, - ), - ) + connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) @@ -295,11 +250,8 @@ class MobileIconInteractorTest : SysuiTestCase() { fun `icon group - checks default data`() = runBlocking(IMMEDIATE) { mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID - connectionRepository.setConnectionInfo( - MobileConnectionModel( - resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) - ), - ) + connectionRepository.resolvedNetworkType.value = + DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G)) var latest: MobileIconGroup? = null val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this) @@ -380,9 +332,7 @@ class MobileIconInteractorTest : SysuiTestCase() { var latest: Boolean? = null val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this) - connectionRepository.setConnectionInfo( - MobileConnectionModel(dataConnectionState = DataConnectionState.Connected) - ) + connectionRepository.dataConnectionState.value = DataConnectionState.Connected yield() assertThat(latest).isTrue() @@ -396,9 +346,7 @@ class MobileIconInteractorTest : SysuiTestCase() { var latest: Boolean? = null val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this) - connectionRepository.setConnectionInfo( - MobileConnectionModel(dataConnectionState = DataConnectionState.Disconnected) - ) + connectionRepository.dataConnectionState.value = DataConnectionState.Disconnected assertThat(latest).isFalse() @@ -411,11 +359,11 @@ class MobileIconInteractorTest : SysuiTestCase() { var latest: Boolean? = null val job = underTest.isInService.onEach { latest = it }.launchIn(this) - connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = true)) + connectionRepository.isInService.value = true assertThat(latest).isTrue() - connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = false)) + connectionRepository.isInService.value = false assertThat(latest).isFalse() @@ -429,22 +377,13 @@ class MobileIconInteractorTest : SysuiTestCase() { val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) connectionRepository.cdmaRoaming.value = true - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = true, - isRoaming = false, - ) - ) + connectionRepository.isGsm.value = true + connectionRepository.isRoaming.value = false yield() assertThat(latest).isFalse() - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = true, - isRoaming = true, - ) - ) + connectionRepository.isRoaming.value = true yield() assertThat(latest).isTrue() @@ -459,23 +398,15 @@ class MobileIconInteractorTest : SysuiTestCase() { val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) connectionRepository.cdmaRoaming.value = false - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = false, - isRoaming = true, - ) - ) + connectionRepository.isGsm.value = false + connectionRepository.isRoaming.value = true yield() assertThat(latest).isFalse() connectionRepository.cdmaRoaming.value = true - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = false, - isRoaming = false, - ) - ) + connectionRepository.isGsm.value = false + connectionRepository.isRoaming.value = false yield() assertThat(latest).isTrue() @@ -490,25 +421,15 @@ class MobileIconInteractorTest : SysuiTestCase() { val job = underTest.isRoaming.onEach { latest = it }.launchIn(this) connectionRepository.cdmaRoaming.value = true - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = false, - isRoaming = true, - carrierNetworkChangeActive = true, - ) - ) + connectionRepository.isGsm.value = false + connectionRepository.isRoaming.value = true + connectionRepository.carrierNetworkChangeActive.value = true yield() assertThat(latest).isFalse() connectionRepository.cdmaRoaming.value = true - connectionRepository.setConnectionInfo( - MobileConnectionModel( - isGsm = true, - isRoaming = true, - carrierNetworkChangeActive = true, - ) - ) + connectionRepository.isGsm.value = true yield() assertThat(latest).isFalse() @@ -526,24 +447,20 @@ class MobileIconInteractorTest : SysuiTestCase() { // Default network name, operator name is non-null, uses the operator name connectionRepository.networkName.value = DEFAULT_NAME - connectionRepository.setConnectionInfo( - MobileConnectionModel(operatorAlphaShort = testOperatorName) - ) + connectionRepository.operatorAlphaShort.value = testOperatorName yield() assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName)) // Default network name, operator name is null, uses the default - connectionRepository.setConnectionInfo(MobileConnectionModel(operatorAlphaShort = null)) + 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.setConnectionInfo( - MobileConnectionModel(operatorAlphaShort = testOperatorName) - ) + connectionRepository.operatorAlphaShort.value = testOperatorName yield() assertThat(latest).isEqualTo(DERIVED_NAME) From 49f1e9e05a144ba357889732fe86d2ed85a95c6c Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Tue, 28 Feb 2023 17:26:27 -0500 Subject: [PATCH 2/3] [Sb refactor] Move DemoMobileConnectionRepository to its own file This class has outgrown being a small data class defined in the same file as its parent repo. Test: DemoMobileConnectionsRepositoryTest; DemoMobileConnectionParameterizedTest Bug: 270300839 Change-Id: I4981e641c0d4c8346ec46a5a832044df62051a8f --- .../demo/DemoMobileConnectionRepository.kt | 231 ++++++++++++++++++ .../demo/DemoMobileConnectionsRepository.kt | 118 +-------- .../DemoMobileConnectionParameterizedTest.kt | 22 +- .../DemoMobileConnectionsRepositoryTest.kt | 27 +- 4 files changed, 278 insertions(+), 120 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt 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 new file mode 100644 index 0000000000000..809772eec2f0f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt @@ -0,0 +1,231 @@ +/* + * 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.data.repository.demo + +import android.telephony.CellSignalStrength +import android.telephony.TelephonyManager +import com.android.systemui.log.table.TableLogBuffer +import com.android.systemui.log.table.logDiffsForTable +import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState +import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel +import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType +import com.android.systemui.statusbar.pipeline.mobile.data.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_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 +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING +import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel +import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel +import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn + +/** + * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using + * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular + * [MutableStateFlow] while still logging all of the inputs in the same manor as the production + * repos. + */ +class DemoMobileConnectionRepository( + override val subId: Int, + override val tableLogBuffer: TableLogBuffer, + val scope: CoroutineScope, +) : MobileConnectionRepository { + private val _isEmergencyOnly = MutableStateFlow(false) + override val isEmergencyOnly = + _isEmergencyOnly + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_EMERGENCY, + _isEmergencyOnly.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value) + + private val _isRoaming = MutableStateFlow(false) + override val isRoaming = + _isRoaming + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_ROAMING, + _isRoaming.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value) + + private val _operatorAlphaShort: MutableStateFlow = MutableStateFlow(null) + override val operatorAlphaShort = + _operatorAlphaShort + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_OPERATOR, + _operatorAlphaShort.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value) + + private val _isInService = MutableStateFlow(false) + override val isInService = + _isInService + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_IN_SERVICE, + _isInService.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value) + + private val _isGsm = MutableStateFlow(false) + override val isGsm = + _isGsm + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_GSM, + _isGsm.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value) + + private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + override val cdmaLevel = + _cdmaLevel + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_CDMA_LEVEL, + _cdmaLevel.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value) + + private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) + override val primaryLevel = + _primaryLevel + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_PRIMARY_LEVEL, + _primaryLevel.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value) + + private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected) + override val dataConnectionState = + _dataConnectionState + .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value) + .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value) + + private val _dataActivityDirection = + MutableStateFlow( + DataActivityModel( + hasActivityIn = false, + hasActivityOut = false, + ) + ) + override val dataActivityDirection = + _dataActivityDirection + .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value) + .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value) + + private val _carrierNetworkChangeActive = MutableStateFlow(false) + override val carrierNetworkChangeActive = + _carrierNetworkChangeActive + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_CARRIER_NETWORK_CHANGE, + _carrierNetworkChangeActive.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value) + + private val _resolvedNetworkType: MutableStateFlow = + MutableStateFlow(ResolvedNetworkType.UnknownNetworkType) + override val resolvedNetworkType = + _resolvedNetworkType + .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value) + .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value) + + override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS) + + override val dataEnabled = MutableStateFlow(true) + + override val cdmaRoaming = MutableStateFlow(false) + + override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network")) + + /** + * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately + * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level + * repository. + */ + fun processDemoMobileEvent( + event: FakeNetworkEventModel.Mobile, + resolvedNetworkType: ResolvedNetworkType, + ) { + // This is always true here, because we split out disabled states at the data-source level + dataEnabled.value = true + networkName.value = NetworkNameModel.IntentDerived(event.name) + + cdmaRoaming.value = event.roaming + _isRoaming.value = event.roaming + // TODO(b/261029387): not yet supported + _isEmergencyOnly.value = false + _operatorAlphaShort.value = event.name + _isInService.value = (event.level ?: 0) > 0 + // TODO(b/261029387): not yet supported + _isGsm.value = false + _cdmaLevel.value = event.level ?: 0 + _primaryLevel.value = event.level ?: 0 + // TODO(b/261029387): not yet supported + _dataConnectionState.value = DataConnectionState.Connected + _dataActivityDirection.value = + (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel() + _carrierNetworkChangeActive.value = event.carrierNetworkChange + _resolvedNetworkType.value = resolvedNetworkType + } + + fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) { + // 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) + numberOfLevels.value = event.numberOfLevels + cdmaRoaming.value = false + _primaryLevel.value = event.level + _cdmaLevel.value = event.level + _dataActivityDirection.value = event.activity.toMobileDataActivityModel() + + // These fields are always the same for carrier-merged networks + _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType + _dataConnectionState.value = DataConnectionState.Connected + _isRoaming.value = false + _isEmergencyOnly.value = false + _operatorAlphaShort.value = null + _isInService.value = true + _isGsm.value = false + _carrierNetworkChangeActive.value = false + } + + companion object { + private const val CARRIER_MERGED_NAME = "Carrier Merged Network" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt index 2b66758bb4b53..3cafb73772601 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt @@ -17,19 +17,14 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo import android.content.Context -import android.telephony.CellSignalStrength import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID -import android.telephony.TelephonyManager import android.util.Log import com.android.settingslib.SignalIcon import com.android.settingslib.mobile.MobileMappings import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.log.table.TableLogBufferFactory -import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel -import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel @@ -39,8 +34,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE -import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel import javax.inject.Inject @@ -52,7 +45,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -191,6 +183,7 @@ constructor( DemoMobileConnectionRepository( subId, tableLogBuffer, + scope, ) return CacheContainer(repo, lastMobileState = null) } @@ -338,112 +331,3 @@ class CacheContainer( /** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */ var lastMobileState: Mobile?, ) - -class DemoMobileConnectionRepository( - override val subId: Int, - override val tableLogBuffer: TableLogBuffer, -) : MobileConnectionRepository { - private val _isEmergencyOnly = MutableStateFlow(false) - override val isEmergencyOnly = _isEmergencyOnly.asStateFlow() - - private val _isRoaming = MutableStateFlow(false) - override val isRoaming = _isRoaming.asStateFlow() - - private val _operatorAlphaShort: MutableStateFlow = MutableStateFlow(null) - override val operatorAlphaShort = _operatorAlphaShort.asStateFlow() - - private val _isInService = MutableStateFlow(false) - override val isInService = _isInService.asStateFlow() - - private val _isGsm = MutableStateFlow(false) - override val isGsm = _isGsm.asStateFlow() - - private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) - override val cdmaLevel = _cdmaLevel.asStateFlow() - - private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) - override val primaryLevel = _primaryLevel.asStateFlow() - - private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected) - override val dataConnectionState = _dataConnectionState.asStateFlow() - - private val _dataActivityDirection = - MutableStateFlow( - DataActivityModel( - hasActivityIn = false, - hasActivityOut = false, - ) - ) - override val dataActivityDirection = _dataActivityDirection.asStateFlow() - - private val _carrierNetworkChangeActive = MutableStateFlow(false) - override val carrierNetworkChangeActive = _carrierNetworkChangeActive.asStateFlow() - - private val _resolvedNetworkType: MutableStateFlow = - MutableStateFlow(ResolvedNetworkType.UnknownNetworkType) - override val resolvedNetworkType = _resolvedNetworkType.asStateFlow() - - override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS) - - override val dataEnabled = MutableStateFlow(true) - - override val cdmaRoaming = MutableStateFlow(false) - - override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network")) - - /** - * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately - * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level - * repository. - */ - fun processDemoMobileEvent( - event: FakeNetworkEventModel.Mobile, - resolvedNetworkType: ResolvedNetworkType, - ) { - // This is always true here, because we split out disabled states at the data-source level - dataEnabled.value = true - networkName.value = NetworkNameModel.IntentDerived(event.name) - - cdmaRoaming.value = event.roaming - _isRoaming.value = event.roaming - // TODO(b/261029387): not yet supported - _isEmergencyOnly.value = false - _operatorAlphaShort.value = event.name - _isInService.value = (event.level ?: 0) > 0 - // TODO(b/261029387): not yet supported - _isGsm.value = false - _cdmaLevel.value = event.level ?: 0 - _primaryLevel.value = event.level ?: 0 - // TODO(b/261029387): not yet supported - _dataConnectionState.value = DataConnectionState.Connected - _dataActivityDirection.value = - (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel() - _carrierNetworkChangeActive.value = event.carrierNetworkChange - _resolvedNetworkType.value = resolvedNetworkType - } - - fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) { - // 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) - numberOfLevels.value = event.numberOfLevels - cdmaRoaming.value = false - _primaryLevel.value = event.level - _cdmaLevel.value = event.level - _dataActivityDirection.value = event.activity.toMobileDataActivityModel() - - // These fields are always the same for carrier-merged networks - _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType - _dataConnectionState.value = DataConnectionState.Connected - _isRoaming.value = false - _isEmergencyOnly.value = false - _operatorAlphaShort.value = null - _isInService.value = true - _isGsm.value = false - _carrierNetworkChangeActive.value = false - } - - companion object { - private const val CARRIER_MERGED_NAME = "Carrier Merged Network" - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index 4a2dce4f7965b..37fac3458c83e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -35,8 +35,11 @@ import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest @@ -122,10 +125,25 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC assertConnection(underTest, networkModel) } - private fun assertConnection( + private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job { + val job = launch { + launch { conn.cdmaLevel.collect {} } + launch { conn.primaryLevel.collect {} } + launch { conn.dataActivityDirection.collect {} } + launch { conn.carrierNetworkChangeActive.collect {} } + launch { conn.isRoaming.collect {} } + launch { conn.networkName.collect {} } + launch { conn.isEmergencyOnly.collect {} } + launch { conn.dataConnectionState.collect {} } + } + return job + } + + private fun TestScope.assertConnection( conn: DemoMobileConnectionRepository, model: FakeNetworkEventModel ) { + val job = startCollection(underTest) when (model) { is FakeNetworkEventModel.Mobile -> { assertThat(conn.subId).isEqualTo(model.subId) @@ -148,6 +166,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC // DemoMobileConnectionsRepositoryTest.kt else -> {} } + + job.cancel() } /** Matches [FakeNetworkEventModel] */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index c8b1d3021c42b..0e45d8ea55634 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -39,9 +39,11 @@ import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import junit.framework.Assert import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest @@ -523,10 +525,27 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { job.cancel() } - private fun assertConnection( + private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job { + val job = launch { + launch { conn.cdmaLevel.collect {} } + launch { conn.primaryLevel.collect {} } + launch { conn.dataActivityDirection.collect {} } + launch { conn.carrierNetworkChangeActive.collect {} } + launch { conn.isRoaming.collect {} } + launch { conn.networkName.collect {} } + launch { conn.isEmergencyOnly.collect {} } + launch { conn.dataConnectionState.collect {} } + } + return job + } + + private fun TestScope.assertConnection( conn: DemoMobileConnectionRepository, model: FakeNetworkEventModel, ) { + val job = startCollection(conn) + // Assert the fields using the `MutableStateFlow` so that we don't have to start up + // a collector for every field for every test when (model) { is FakeNetworkEventModel.Mobile -> { assertThat(conn.subId).isEqualTo(model.subId) @@ -547,12 +566,15 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { } else -> {} } + + job.cancel() } - private fun assertCarrierMergedConnection( + private fun TestScope.assertCarrierMergedConnection( conn: DemoMobileConnectionRepository, model: FakeWifiEventModel.CarrierMerged, ) { + val job = startCollection(conn) assertThat(conn.subId).isEqualTo(model.subscriptionId) assertThat(conn.cdmaLevel.value).isEqualTo(model.level) assertThat(conn.primaryLevel.value).isEqualTo(model.level) @@ -561,6 +583,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(conn.isEmergencyOnly.value).isFalse() assertThat(conn.isGsm.value).isFalse() assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected) + job.cancel() } } From e5e9b8cfaff0cbfdcfc5b461841b30861eb1a5f6 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Mon, 6 Mar 2023 17:05:49 -0500 Subject: [PATCH 3/3] [Sb refactor] Use MobileMappings key for Unknown net types ResolvedNetworkType.UnknownNetworkType was using "unknown" as the key, but MobileMappings actually can potentially have some embedded information about which network type icon to display in the case of unknown. This would also always cause a lookup failure, causing the G network indicator to show in cases where it should not be. Test: MobileConnectionRepositoryTest Bug: 269040632 Change-Id: I61f450faa756487983f300ff9dfefdcb74424e43 --- .../mobile/data/model/ResolvedNetworkType.kt | 4 +++- .../prod/MobileConnectionRepositoryTest.kt | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt index bacf34fa2d606..cf7a313a4cb1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt @@ -17,7 +17,9 @@ package com.android.systemui.statusbar.pipeline.mobile.data.model import android.telephony.Annotation.NetworkType +import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN import com.android.settingslib.SignalIcon +import com.android.settingslib.mobile.MobileMappings import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.log.table.Diffable import com.android.systemui.log.table.TableRowLogger @@ -38,7 +40,7 @@ sealed interface ResolvedNetworkType : Diffable { } object UnknownNetworkType : ResolvedNetworkType { - override val lookupKey: String = "unknown" + override val lookupKey: String = MobileMappings.toIconKey(NETWORK_TYPE_UNKNOWN) override fun toString(): String = "Unknown" } 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 abc722a94c852..f6e595924f586 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 @@ -50,7 +50,9 @@ import android.telephony.TelephonyManager.EXTRA_SHOW_SPN import android.telephony.TelephonyManager.EXTRA_SPN import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID import android.telephony.TelephonyManager.NETWORK_TYPE_LTE +import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN import androidx.test.filters.SmallTest +import com.android.settingslib.mobile.MobileMappings import com.android.systemui.SysuiTestCase import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger @@ -391,6 +393,24 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { job.cancel() } + @Test + fun networkType_unknown_hasCorrectKey() = + runBlocking(IMMEDIATE) { + var latest: ResolvedNetworkType? = null + val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this) + + val callback = getTelephonyCallbackForType() + val type = NETWORK_TYPE_UNKNOWN + val expected = UnknownNetworkType + val ti = mock().also { whenever(it.networkType).thenReturn(type) } + callback.onDisplayInfoChanged(ti) + + assertThat(latest).isEqualTo(expected) + assertThat(latest!!.lookupKey).isEqualTo(MobileMappings.toIconKey(type)) + + job.cancel() + } + @Test fun networkType_updatesUsingDefault() = runBlocking(IMMEDIATE) {