[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
This commit is contained in:
Evan Laird
2023-02-24 17:44:52 -05:00
parent 0f7e276a99
commit 5cbcba28d6
17 changed files with 872 additions and 905 deletions

View File

@@ -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<DataConnectionState> {
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 =

View File

@@ -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<MobileConnectionModel> {
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"
}
}

View File

@@ -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<ResolvedNetworkType> {
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"
}
}

View File

@@ -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<Boolean>
/** True if [android.telephony.ServiceState] says we are roaming */
val isRoaming: StateFlow<Boolean>
/**
* 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<MobileConnectionModel>
val operatorAlphaShort: StateFlow<String?>
/**
* 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<Boolean>
/** True if [android.telephony.SignalStrength] told us that this connection is using GSM */
val isGsm: StateFlow<Boolean>
/**
* 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<Int>
/** [android.telephony.SignalStrength]'s concept of the overall signal level */
// @IntRange(from = 0, to = 4)
val primaryLevel: StateFlow<Int>
/** The current data connection state. See [DataConnectionState] */
val dataConnectionState: StateFlow<DataConnectionState>
/** The current data activity direction. See [DataActivityModel] */
val dataActivityDirection: StateFlow<DataActivityModel>
/** True if there is currently a carrier network change in process */
val carrierNetworkChangeActive: StateFlow<Boolean>
/**
* [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<ResolvedNetworkType>
/** The total number of levels. Used with [SignalDrawable]. */
val numberOfLevels: StateFlow<Int>

View File

@@ -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<String?> = 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<ResolvedNetworkType> =
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"
}
}

View File

@@ -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<MobileConnectionModel> =
combine(network, wifiRepository.wifiActivity) { network, activity ->
if (network == null) {
MobileConnectionModel()
} else {
createCarrierMergedConnectionModel(network.level, activity)
}
}
.stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(ROAMING).asStateFlow()
override val networkName: StateFlow<NetworkNameModel> =
@@ -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<Boolean> = 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
}

View File

@@ -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"
}
}

View File

@@ -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<CallbackEvent.OnServiceStateChanged>()
.map { it.serviceState.isEmergencyOnly }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val isRoaming =
callbackEvents
.filterIsInstance<CallbackEvent.OnServiceStateChanged>()
.map { it.serviceState.roaming }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val operatorAlphaShort =
callbackEvents
.filterIsInstance<CallbackEvent.OnServiceStateChanged>()
.map { it.serviceState.operatorAlphaShort }
.stateIn(scope, SharingStarted.WhileSubscribed(), null)
override val isInService =
callbackEvents
.filterIsInstance<CallbackEvent.OnServiceStateChanged>()
.map { Utils.isInService(it.serviceState) }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val isGsm =
callbackEvents
.filterIsInstance<CallbackEvent.OnSignalStrengthChanged>()
.map { it.signalStrength.isGsm }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val cdmaLevel =
callbackEvents
.filterIsInstance<CallbackEvent.OnSignalStrengthChanged>()
.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<CallbackEvent.OnSignalStrengthChanged>()
.map { it.signalStrength.level }
.stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
override val dataConnectionState =
callbackEvents
.filterIsInstance<CallbackEvent.OnDataConnectionStateChanged>()
.map { it.dataState.toDataConnectionType() }
.stateIn(scope, SharingStarted.WhileSubscribed(), Disconnected)
override val dataActivityDirection =
callbackEvents
.filterIsInstance<CallbackEvent.OnDataActivity>()
.map { it.direction.toMobileDataActivityModel() }
.stateIn(
scope,
SharingStarted.WhileSubscribed(),
DataActivityModel(hasActivityIn = false, hasActivityOut = false)
)
override val carrierNetworkChangeActive =
callbackEvents
.filterIsInstance<CallbackEvent.OnCarrierNetworkChange>()
.map { it.active }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val resolvedNetworkType =
callbackEvents
.filterIsInstance<CallbackEvent.OnDisplayInfoChanged>()
.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

View File

@@ -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<Boolean>,
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<Boolean> = 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<MobileIconGroup> =
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<Boolean> =
connectionInfo
.mapLatest { it.isEmergencyOnly }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val isEmergencyOnly = connectionRepository.isEmergencyOnly
override val isRoaming: StateFlow<Boolean> =
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<Int> =
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<Boolean> =
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
}

View File

@@ -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<Pair<String, String>>()
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()))
}
}
}

View File

@@ -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<String?> = 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<ResolvedNetworkType> =
MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
@@ -40,10 +53,6 @@ class FakeMobileConnectionRepository(
override val networkName =
MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
fun setConnectionInfo(model: MobileConnectionModel) {
_connectionInfo.value = model
}
fun setDataEnabled(enabled: Boolean) {
_dataEnabled.value = enabled
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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()
}

View File

@@ -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<SignalStrength>()
@@ -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<SignalStrength>()
whenever(signalStrength.level).thenReturn(1)

View File

@@ -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<ServiceStateListener>().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<ServiceStateListener>()
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<TelephonyCallback.SignalStrengthsListener>()
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<TelephonyCallback.SignalStrengthsListener>()
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<TelephonyCallback.SignalStrengthsListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<TelephonyCallback.DataConnectionStateListener>()
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<DataActivityListener>()
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<TelephonyCallback.CarrierNetworkListener>()
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<TelephonyCallback.DisplayInfoListener>()
val type = NETWORK_TYPE_LTE
@@ -371,16 +403,16 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
val ti = mock<TelephonyDisplayInfo>().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<TelephonyCallback.DisplayInfoListener>()
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()

View File

@@ -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)