[Sb refactor] Support NetworkName in new mobile pipeline
The network name can come from one of 3 places: 1. TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED, which passes an intent containing a network name which we can derive 2. ServiceState.getOperatorAlphaShort(), from the service state changed telephony callback 3. A default value, set in the framework config `lockscreen_carrier_default` Based on the implementation that currently lives in `MobileSignalController`, we were only using `NetworkName` a.k.a. `EXTRA_SPN`, and not `NetworkNameData` a.k.a. `EXTRA_DATA_SPN`. Therefore this CL only adds support for the former. The front end does not consume this piece of data yet, since it is only needed for QuickSettings. Future CLs will add support for a LocationBasedMobileViewModel (similar to Wi-Fi), which can then start consuming the values. Test: MobileConnectionRepositoryTest Test: DemoMobileConnectionsRepositoryTest Test: MobileIconInteractorTest Bug: 238425913 Change-Id: I04fa90bf7b52aa992f9721c7301f541f6085cf68
This commit is contained in:
@@ -39,33 +39,42 @@ import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityMod
|
||||
* threading complex system objects through the pipeline.
|
||||
*/
|
||||
data class MobileConnectionModel(
|
||||
/** From [ServiceStateListener.onServiceStateChanged] */
|
||||
/** 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,
|
||||
|
||||
/** From [SignalStrengthsListener.onSignalStrengthsChanged] */
|
||||
/** 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,
|
||||
|
||||
/** Mapped from [DataConnectionStateListener.onDataConnectionStateChanged] */
|
||||
/** Fields below from [DataConnectionStateListener.onDataConnectionStateChanged] */
|
||||
val dataConnectionState: DataConnectionState = Disconnected,
|
||||
|
||||
/** From [DataActivityListener.onDataActivity]. See [TelephonyManager] for the values */
|
||||
/**
|
||||
* Fields below from [DataActivityListener.onDataActivity]. See [TelephonyManager] for the
|
||||
* values
|
||||
*/
|
||||
val dataActivityDirection: DataActivityModel =
|
||||
DataActivityModel(
|
||||
hasActivityIn = false,
|
||||
hasActivityOut = false,
|
||||
),
|
||||
|
||||
/** From [CarrierNetworkListener.onCarrierNetworkChange] */
|
||||
/** Fields below from [CarrierNetworkListener.onCarrierNetworkChange] */
|
||||
val carrierNetworkChangeActive: Boolean = false,
|
||||
|
||||
/** Fields below from [DisplayInfoListener.onDisplayInfoChanged]. */
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.content.Intent
|
||||
import android.telephony.TelephonyManager.EXTRA_DATA_SPN
|
||||
import android.telephony.TelephonyManager.EXTRA_PLMN
|
||||
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
|
||||
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
|
||||
|
||||
/**
|
||||
* Encapsulates the data needed to show a network name for a mobile network. The data is parsed from
|
||||
* the intent sent by [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED].
|
||||
*/
|
||||
sealed interface NetworkNameModel {
|
||||
val name: String
|
||||
|
||||
/** The default name is read from [com.android.internal.R.string.lockscreen_carrier_default] */
|
||||
data class Default(override val name: String) : NetworkNameModel
|
||||
|
||||
/**
|
||||
* This name has been derived from telephony intents. see
|
||||
* [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED]
|
||||
*/
|
||||
data class Derived(override val name: String) : NetworkNameModel
|
||||
}
|
||||
|
||||
fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
|
||||
val showSpn = getBooleanExtra(EXTRA_SHOW_SPN, false)
|
||||
val spn = getStringExtra(EXTRA_DATA_SPN)
|
||||
val showPlmn = getBooleanExtra(EXTRA_SHOW_PLMN, false)
|
||||
val plmn = getStringExtra(EXTRA_PLMN)
|
||||
|
||||
val str = StringBuilder()
|
||||
val strData = StringBuilder()
|
||||
if (showPlmn && plmn != null) {
|
||||
str.append(plmn)
|
||||
strData.append(plmn)
|
||||
}
|
||||
if (showSpn && spn != null) {
|
||||
if (str.isNotEmpty()) {
|
||||
str.append(separator)
|
||||
}
|
||||
str.append(spn)
|
||||
}
|
||||
|
||||
return if (str.isNotEmpty()) NetworkNameModel.Derived(str.toString()) else null
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.telephony.SubscriptionManager
|
||||
import android.telephony.TelephonyCallback
|
||||
import android.telephony.TelephonyManager
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
@@ -58,4 +59,7 @@ interface MobileConnectionRepository {
|
||||
* True if the Enhanced Roaming Indicator (ERI) display number is not [TelephonyManager.ERI_OFF]
|
||||
*/
|
||||
val cdmaRoaming: StateFlow<Boolean>
|
||||
|
||||
/** The service provider name for this network connection, or the default name */
|
||||
val networkName: StateFlow<NetworkNameModel>
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.systemui.dagger.qualifiers.Application
|
||||
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
|
||||
@@ -187,6 +188,7 @@ constructor(
|
||||
// This is always true here, because we split out disabled states at the data-source level
|
||||
connection.dataEnabled.value = true
|
||||
connection.isDefaultDataSubscription.value = state.dataType != null
|
||||
connection.networkName.value = NetworkNameModel.Derived(state.name)
|
||||
|
||||
connection.cdmaRoaming.value = state.roaming
|
||||
connection.connectionInfo.value = state.toMobileConnectionModel()
|
||||
@@ -266,4 +268,6 @@ class DemoMobileConnectionRepository(override val subId: Int) : MobileConnection
|
||||
override val isDefaultDataSubscription = MutableStateFlow(true)
|
||||
|
||||
override val cdmaRoaming = MutableStateFlow(false)
|
||||
|
||||
override val networkName = MutableStateFlow(NetworkNameModel.Derived("demo network"))
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ constructor(
|
||||
val activity = getString("activity")?.toActivity()
|
||||
val carrierNetworkChange = getString("carriernetworkchange") == "show"
|
||||
val roaming = getString("roam") == "show"
|
||||
val name = getString("networkname") ?: "demo mode"
|
||||
|
||||
return Mobile(
|
||||
level = level,
|
||||
@@ -109,6 +110,7 @@ constructor(
|
||||
activity = activity,
|
||||
carrierNetworkChange = carrierNetworkChange,
|
||||
roaming = roaming,
|
||||
name = name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ sealed interface FakeNetworkEventModel {
|
||||
@DataActivityType val activity: Int?,
|
||||
val carrierNetworkChange: Boolean,
|
||||
val roaming: Boolean,
|
||||
val name: String,
|
||||
) : FakeNetworkEventModel
|
||||
|
||||
data class MobileDisabled(
|
||||
|
||||
@@ -17,26 +17,32 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
|
||||
|
||||
import android.content.Context
|
||||
import android.content.IntentFilter
|
||||
import android.database.ContentObserver
|
||||
import android.provider.Settings.Global
|
||||
import android.telephony.CellSignalStrength
|
||||
import android.telephony.CellSignalStrengthCdma
|
||||
import android.telephony.ServiceState
|
||||
import android.telephony.SignalStrength
|
||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
import android.telephony.TelephonyCallback
|
||||
import android.telephony.TelephonyDisplayInfo
|
||||
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.TelephonyManager.ERI_OFF
|
||||
import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
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.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.toDataConnectionType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
@@ -63,8 +69,11 @@ import kotlinx.coroutines.flow.stateIn
|
||||
class MobileConnectionRepositoryImpl(
|
||||
private val context: Context,
|
||||
override val subId: Int,
|
||||
defaultNetworkName: NetworkNameModel,
|
||||
networkNameSeparator: String,
|
||||
private val telephonyManager: TelephonyManager,
|
||||
private val globalSettings: GlobalSettings,
|
||||
broadcastDispatcher: BroadcastDispatcher,
|
||||
defaultDataSubId: StateFlow<Int>,
|
||||
globalMobileDataSettingChangedEvent: Flow<Unit>,
|
||||
mobileMappingsProxy: MobileMappingsProxy,
|
||||
@@ -101,6 +110,7 @@ class MobileConnectionRepositoryImpl(
|
||||
state.copy(
|
||||
isEmergencyOnly = serviceState.isEmergencyOnly,
|
||||
isRoaming = serviceState.roaming,
|
||||
operatorAlphaShort = serviceState.operatorAlphaShort,
|
||||
)
|
||||
trySend(state)
|
||||
}
|
||||
@@ -222,6 +232,19 @@ class MobileConnectionRepositoryImpl(
|
||||
.mapLatest { telephonyManager.cdmaEnhancedRoamingIndicatorDisplayNumber != ERI_OFF }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
override val networkName: StateFlow<NetworkNameModel> =
|
||||
broadcastDispatcher
|
||||
.broadcastFlow(IntentFilter(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED)) {
|
||||
intent,
|
||||
_ ->
|
||||
if (intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, INVALID_SUBSCRIPTION_ID) != subId) {
|
||||
defaultNetworkName
|
||||
} else {
|
||||
intent.toNetworkNameModel(networkNameSeparator) ?: defaultNetworkName
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
|
||||
|
||||
override val dataEnabled: StateFlow<Boolean> =
|
||||
telephonyPollingEvent
|
||||
.mapLatest { dataConnectionAllowed() }
|
||||
@@ -237,6 +260,7 @@ class MobileConnectionRepositoryImpl(
|
||||
class Factory
|
||||
@Inject
|
||||
constructor(
|
||||
private val broadcastDispatcher: BroadcastDispatcher,
|
||||
private val context: Context,
|
||||
private val telephonyManager: TelephonyManager,
|
||||
private val logger: ConnectivityPipelineLogger,
|
||||
@@ -247,14 +271,19 @@ class MobileConnectionRepositoryImpl(
|
||||
) {
|
||||
fun build(
|
||||
subId: Int,
|
||||
defaultNetworkName: NetworkNameModel,
|
||||
networkNameSeparator: String,
|
||||
defaultDataSubId: StateFlow<Int>,
|
||||
globalMobileDataSettingChangedEvent: Flow<Unit>,
|
||||
): MobileConnectionRepository {
|
||||
return MobileConnectionRepositoryImpl(
|
||||
context,
|
||||
subId,
|
||||
defaultNetworkName,
|
||||
networkNameSeparator,
|
||||
telephonyManager.createForSubscriptionId(subId),
|
||||
globalSettings,
|
||||
broadcastDispatcher,
|
||||
defaultDataSubId,
|
||||
globalMobileDataSettingChangedEvent,
|
||||
mobileMappingsProxy,
|
||||
|
||||
@@ -38,12 +38,14 @@ import androidx.annotation.VisibleForTesting
|
||||
import com.android.internal.telephony.PhoneConstants
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.settingslib.mobile.MobileMappings.Config
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
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.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
|
||||
@@ -88,6 +90,14 @@ constructor(
|
||||
) : MobileConnectionsRepository {
|
||||
private var subIdRepositoryCache: MutableMap<Int, MobileConnectionRepository> = mutableMapOf()
|
||||
|
||||
private val defaultNetworkName =
|
||||
NetworkNameModel.Default(
|
||||
context.getString(com.android.internal.R.string.lockscreen_carrier_default)
|
||||
)
|
||||
|
||||
private val networkNameSeparator: String =
|
||||
context.getString(R.string.status_bar_network_name_separator)
|
||||
|
||||
/**
|
||||
* State flow that emits the set of mobile data subscriptions, each represented by its own
|
||||
* [SubscriptionInfo]. We probably only need the [SubscriptionInfo.getSubscriptionId] of each
|
||||
@@ -243,6 +253,8 @@ constructor(
|
||||
private fun createRepositoryForSubId(subId: Int): MobileConnectionRepository {
|
||||
return mobileConnectionRepositoryFactory.build(
|
||||
subId,
|
||||
defaultNetworkName,
|
||||
networkNameSeparator,
|
||||
defaultDataSubId,
|
||||
globalMobileDataSettingChangedEvent,
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.telephony.CarrierConfigManager
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||
import com.android.systemui.util.CarrierConfigTracker
|
||||
@@ -56,6 +57,15 @@ interface MobileIconInteractor {
|
||||
/** Observable for RAT type (network type) indicator */
|
||||
val networkTypeIconGroup: StateFlow<MobileIconGroup>
|
||||
|
||||
/**
|
||||
* Provider name for this network connection. The name can be one of 3 values:
|
||||
* 1. The default network name, if one is configured
|
||||
* 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
|
||||
* 3. Or, in the case where the repository sends us the default network name, we check for an
|
||||
* override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
|
||||
*/
|
||||
val networkName: StateFlow<NetworkNameModel>
|
||||
|
||||
/** True if this line of service is emergency-only */
|
||||
val isEmergencyOnly: StateFlow<Boolean>
|
||||
|
||||
@@ -93,6 +103,22 @@ class MobileIconInteractorImpl(
|
||||
|
||||
override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled
|
||||
|
||||
override val networkName =
|
||||
combine(connectionInfo, connectionRepository.networkName) { connection, networkName ->
|
||||
if (
|
||||
networkName is NetworkNameModel.Default && connection.operatorAlphaShort != null
|
||||
) {
|
||||
NetworkNameModel.Derived(connection.operatorAlphaShort)
|
||||
} else {
|
||||
networkName
|
||||
}
|
||||
}
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
connectionRepository.networkName.value
|
||||
)
|
||||
|
||||
/** Observable for the current RAT indicator icon ([MobileIconGroup]) */
|
||||
override val networkTypeIconGroup: StateFlow<MobileIconGroup> =
|
||||
combine(
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
|
||||
@@ -32,6 +33,9 @@ class FakeMobileConnectionRepository(override val subId: Int) : MobileConnection
|
||||
|
||||
override val cdmaRoaming = MutableStateFlow(false)
|
||||
|
||||
override val networkName =
|
||||
MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
|
||||
|
||||
fun setConnectionInfo(model: MobileConnectionModel) {
|
||||
_connectionInfo.value = model
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ 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.repository.demo.model.FakeNetworkEventModel
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
||||
import com.android.systemui.util.mockito.mock
|
||||
@@ -98,6 +99,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
activity = testCase.activity,
|
||||
carrierNetworkChange = testCase.carrierNetworkChange,
|
||||
roaming = testCase.roaming,
|
||||
name = "demo name",
|
||||
)
|
||||
|
||||
fakeNetworkEventFlow.value = networkModel
|
||||
@@ -121,6 +123,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
assertThat(connectionInfo.carrierNetworkChangeActive)
|
||||
.isEqualTo(model.carrierNetworkChange)
|
||||
assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
|
||||
assertThat(conn.networkName.value).isEqualTo(NetworkNameModel.Derived(model.name))
|
||||
|
||||
// TODO(b/261029387): check these once we start handling them
|
||||
assertThat(connectionInfo.isEmergencyOnly).isFalse()
|
||||
@@ -144,6 +147,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
@Annotation.DataActivityType val activity: Int,
|
||||
val carrierNetworkChange: Boolean,
|
||||
val roaming: Boolean,
|
||||
val name: String,
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "INPUT(level=$level, " +
|
||||
@@ -153,7 +157,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
"inflateStrength=$inflateStrength, " +
|
||||
"activity=$activity, " +
|
||||
"carrierNetworkChange=$carrierNetworkChange, " +
|
||||
"roaming=$roaming)"
|
||||
"roaming=$roaming, " +
|
||||
"name=$name)"
|
||||
}
|
||||
|
||||
// Convenience for iterating test data and creating new cases
|
||||
@@ -166,6 +171,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
@Annotation.DataActivityType activity: Int? = null,
|
||||
carrierNetworkChange: Boolean? = null,
|
||||
roaming: Boolean? = null,
|
||||
name: String? = null,
|
||||
): TestCase =
|
||||
TestCase(
|
||||
level = level ?: this.level,
|
||||
@@ -176,6 +182,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
activity = activity ?: this.activity,
|
||||
carrierNetworkChange = carrierNetworkChange ?: this.carrierNetworkChange,
|
||||
roaming = roaming ?: this.roaming,
|
||||
name = name ?: this.name,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -204,6 +211,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
private val carrierNetworkChange = booleanList
|
||||
// false first so the base case doesn't have roaming set (more common)
|
||||
private val roaming = listOf(false, true)
|
||||
private val names = listOf("name 1", "name 2")
|
||||
|
||||
@Parameters(name = "{0}") @JvmStatic fun data() = testData()
|
||||
|
||||
@@ -239,6 +247,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
activity.first(),
|
||||
carrierNetworkChange.first(),
|
||||
roaming.first(),
|
||||
names.first(),
|
||||
)
|
||||
|
||||
val tail =
|
||||
@@ -249,7 +258,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
inflateStrength.map { baseCase.modifiedBy(inflateStrength = it) },
|
||||
activity.map { baseCase.modifiedBy(activity = it) },
|
||||
carrierNetworkChange.map { baseCase.modifiedBy(carrierNetworkChange = it) },
|
||||
roaming.map { baseCase.modifiedBy(roaming = it) }
|
||||
roaming.map { baseCase.modifiedBy(roaming = it) },
|
||||
names.map { baseCase.modifiedBy(name = it) },
|
||||
)
|
||||
.flatten()
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.android.settingslib.mobile.TelephonyIcons.THREE_G
|
||||
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.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
|
||||
@@ -296,6 +297,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
assertThat(connectionInfo.carrierNetworkChangeActive)
|
||||
.isEqualTo(model.carrierNetworkChange)
|
||||
assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
|
||||
assertThat(conn.networkName.value).isEqualTo(NetworkNameModel.Derived(model.name))
|
||||
|
||||
// TODO(b/261029387) check these once we start handling them
|
||||
assertThat(connectionInfo.isEmergencyOnly).isFalse()
|
||||
@@ -328,4 +330,5 @@ fun validMobileEvent(
|
||||
activity = activity,
|
||||
carrierNetworkChange = carrierNetworkChange,
|
||||
roaming = roaming,
|
||||
name = "demo name",
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.UserHandle
|
||||
import android.provider.Settings
|
||||
import android.telephony.CellSignalStrengthCdma
|
||||
@@ -40,15 +41,22 @@ import android.telephony.TelephonyManager.DATA_DISCONNECTING
|
||||
import android.telephony.TelephonyManager.DATA_UNKNOWN
|
||||
import android.telephony.TelephonyManager.ERI_OFF
|
||||
import android.telephony.TelephonyManager.ERI_ON
|
||||
import android.telephony.TelephonyManager.EXTRA_PLMN
|
||||
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
|
||||
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
|
||||
import android.telephony.TelephonyManager.EXTRA_SPN
|
||||
import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.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.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
@@ -98,8 +106,11 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
MobileConnectionRepositoryImpl(
|
||||
context,
|
||||
SUB_1_ID,
|
||||
DEFAULT_NAME,
|
||||
SEP,
|
||||
telephonyManager,
|
||||
globalSettings,
|
||||
fakeBroadcastDispatcher,
|
||||
connectionsRepo.defaultDataSubId,
|
||||
connectionsRepo.globalMobileDataSettingChangedEvent,
|
||||
mobileMappings,
|
||||
@@ -506,6 +517,74 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network name - default`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: NetworkNameModel? = null
|
||||
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEqualTo(DEFAULT_NAME)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network name - uses broadcast info - returns derived`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: NetworkNameModel? = null
|
||||
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val intent = spnIntent()
|
||||
|
||||
fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
|
||||
receiver.onReceive(context, intent)
|
||||
}
|
||||
|
||||
assertThat(latest).isEqualTo(intent.toNetworkNameModel(SEP))
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network name - broadcast not for this sub id - returns default`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: NetworkNameModel? = null
|
||||
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val intent = spnIntent(subId = 101)
|
||||
|
||||
fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
|
||||
receiver.onReceive(context, intent)
|
||||
}
|
||||
|
||||
assertThat(latest).isEqualTo(DEFAULT_NAME)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network name - operatorAlphaShort - tracked`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: String? = null
|
||||
|
||||
val job =
|
||||
underTest.connectionInfo.onEach { latest = it.operatorAlphaShort }.launchIn(this)
|
||||
|
||||
val shortName = "short name"
|
||||
val serviceState = ServiceState()
|
||||
serviceState.setOperatorName(
|
||||
/* longName */ "long name",
|
||||
/* shortName */ shortName,
|
||||
/* numeric */ "12345",
|
||||
)
|
||||
|
||||
getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
|
||||
|
||||
assertThat(latest).isEqualTo(shortName)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
private fun getTelephonyCallbacks(): List<TelephonyCallback> {
|
||||
val callbackCaptor = argumentCaptor<TelephonyCallback>()
|
||||
Mockito.verify(telephonyManager).registerTelephonyCallback(any(), callbackCaptor.capture())
|
||||
@@ -531,10 +610,31 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
return signalStrength
|
||||
}
|
||||
|
||||
private fun spnIntent(
|
||||
subId: Int = SUB_1_ID,
|
||||
showSpn: Boolean = true,
|
||||
spn: String = SPN,
|
||||
showPlmn: Boolean = true,
|
||||
plmn: String = PLMN,
|
||||
): Intent =
|
||||
Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED).apply {
|
||||
putExtra(EXTRA_SUBSCRIPTION_ID, subId)
|
||||
putExtra(EXTRA_SHOW_SPN, showSpn)
|
||||
putExtra(EXTRA_SPN, spn)
|
||||
putExtra(EXTRA_SHOW_PLMN, showPlmn)
|
||||
putExtra(EXTRA_PLMN, plmn)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||
private const val SUB_1_ID = 1
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
|
||||
|
||||
private val DEFAULT_NAME = NetworkNameModel.Default("default name")
|
||||
private const val SEP = "-"
|
||||
|
||||
private const val SPN = "testSpn"
|
||||
private const val PLMN = "testPlmn"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
|
||||
connectionFactory =
|
||||
MobileConnectionRepositoryImpl.Factory(
|
||||
fakeBroadcastDispatcher,
|
||||
context = context,
|
||||
telephonyManager = telephonyManager,
|
||||
bgDispatcher = IMMEDIATE,
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
||||
import android.telephony.CellSignalStrength
|
||||
import com.android.settingslib.SignalIcon
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@@ -36,6 +37,8 @@ class FakeMobileIconInteractor : MobileIconInteractor {
|
||||
private val _iconGroup = MutableStateFlow<SignalIcon.MobileIconGroup>(TelephonyIcons.THREE_G)
|
||||
override val networkTypeIconGroup = _iconGroup
|
||||
|
||||
override val networkName = MutableStateFlow(NetworkNameModel.Derived("demo mode"))
|
||||
|
||||
private val _isEmergencyOnly = MutableStateFlow(false)
|
||||
override val isEmergencyOnly = _isEmergencyOnly
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ 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.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
|
||||
@@ -392,6 +393,41 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network name - uses operatorAlphaShot when non null and repo is default`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: NetworkNameModel? = null
|
||||
val job = underTest.networkName.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val testOperatorName = "operatorAlphaShort"
|
||||
|
||||
// Default network name, operator name is non-null, uses the operator name
|
||||
connectionRepository.networkName.value = DEFAULT_NAME
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(operatorAlphaShort = testOperatorName)
|
||||
)
|
||||
yield()
|
||||
|
||||
assertThat(latest).isEqualTo(NetworkNameModel.Derived(testOperatorName))
|
||||
|
||||
// Default network name, operator name is null, uses the default
|
||||
connectionRepository.setConnectionInfo(MobileConnectionModel(operatorAlphaShort = 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)
|
||||
)
|
||||
yield()
|
||||
|
||||
assertThat(latest).isEqualTo(DERIVED_NAME)
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||
|
||||
@@ -401,5 +437,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
private const val SUB_1_ID = 1
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
|
||||
|
||||
private val DEFAULT_NAME = NetworkNameModel.Default("test default name")
|
||||
private val DERIVED_NAME = NetworkNameModel.Derived("test derived name")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user