From 502ec03596425a9e2da4dc767f880683d6c3b627 Mon Sep 17 00:00:00 2001 From: Evan Laird <evanlaird@google.com> Date: Tue, 3 Oct 2023 16:35:53 -0400 Subject: [PATCH] [Sb] Add prioritize_latency tracking in mobile connections This CL adds a network callback -- registered via ConnectivityManager -- for every mobile subscription that we know about. This amounts to one listeners per subId (more on that below). The network callback is registered only to receive information about _that_ subId's network pertaining to the NET_CAPABILITY_PRIORITIZE_LATENCY. We'll use this flag downstream to determine whether or not to show a network slice attribution. On ConnectivityManager's callback list: The docs on ConnectivityManagerService claims that we should be careful about too many callbacks registered with the system. If we need to get rid of the 1:1 mapping from subscription to registrant, then we would have to do some work to register a _single_ callback that maintained a map of <netId, networkCapabilities>. It would also presumably have to be eagerly listening, and make sure to update the map whenever a network disappears Note that this doesn't actually give us a huge performance benefit from what I can tell. This is because our single registrant would still get a callback-per-network in which the capabilities changed. Therefore, we still get the penalty of N incoming IPCs when there are N networks that meet the criteria. So we only should worry about that in the case where we run close to the limit of 100 subscribers per process. Test: tests in statusbar/pipeline Bug: 270385675 Change-Id: If42b52ad6e14bdc258c90761e3e6dd629bbe9d3d --- .../pipeline/mobile/data/MobileInputLogger.kt | 18 +++++++ .../repository/MobileConnectionRepository.kt | 6 +++ .../demo/DemoMobileConnectionRepository.kt | 4 ++ .../DemoModeMobileConnectionDataSource.kt | 2 + .../demo/model/FakeNetworkEventModel.kt | 1 + .../prod/CarrierMergedConnectionRepository.kt | 7 +++ .../prod/FullMobileConnectionRepository.kt | 9 ++++ .../prod/MobileConnectionRepositoryImpl.kt | 52 +++++++++++++++++++ .../FakeMobileConnectionRepository.kt | 2 + .../DemoMobileConnectionParameterizedTest.kt | 12 ++++- .../DemoMobileConnectionsRepositoryTest.kt | 3 ++ .../FullMobileConnectionRepositoryTest.kt | 3 ++ .../prod/MobileConnectionRepositoryTest.kt | 45 ++++++++++++++++ .../MobileConnectionTelephonySmokeTests.kt | 3 ++ .../prod/MobileConnectionsRepositoryTest.kt | 1 + 15 files changed, 167 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt index aacdc6323179..3522b9a13989 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt @@ -190,6 +190,24 @@ constructor( fun logOnSimStateChanged() { buffer.log(TAG, LogLevel.INFO, "onSimStateChanged") } + + fun logPrioritizedNetworkAvailable(netId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { int1 = netId }, + { "Found prioritized network (nedId=$int1)" }, + ) + } + + fun logPrioritizedNetworkLost(netId: Int) { + buffer.log( + TAG, + LogLevel.INFO, + { int1 = netId }, + { "Lost prioritized network (nedId=$int1)" }, + ) + } } private const val TAG = "MobileInputLog" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt index a89b1b2db6b3..679426db99c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt @@ -131,6 +131,12 @@ interface MobileConnectionRepository { */ val isAllowedDuringAirplaneMode: StateFlow<Boolean> + /** + * True if this network has NET_CAPABILITIY_PRIORITIZE_LATENCY, and can be considered to be a + * network slice + */ + val hasPrioritizedNetworkCapabilities: StateFlow<Boolean> + companion object { /** The default number of levels to use for [numberOfLevels]. */ const val DEFAULT_NUM_LEVELS = 4 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt index c576b822da15..caa9d1a8f0c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt @@ -191,6 +191,8 @@ class DemoMobileConnectionRepository( override val isAllowedDuringAirplaneMode = MutableStateFlow(false) + override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false) + /** * 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 @@ -225,6 +227,7 @@ class DemoMobileConnectionRepository( _resolvedNetworkType.value = resolvedNetworkType isAllowedDuringAirplaneMode.value = false + hasPrioritizedNetworkCapabilities.value = event.slice } fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) { @@ -250,6 +253,7 @@ class DemoMobileConnectionRepository( _isGsm.value = false _carrierNetworkChangeActive.value = false isAllowedDuringAirplaneMode.value = true + hasPrioritizedNetworkCapabilities.value = false } companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt index d4ddb856eecf..4cd877eb1a14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt @@ -76,6 +76,7 @@ constructor( val carrierNetworkChange = getString("carriernetworkchange") == "show" val roaming = getString("roam") == "show" val name = getString("networkname") ?: "demo mode" + val slice = getString("slice").toBoolean() return Mobile( level = level, @@ -87,6 +88,7 @@ constructor( carrierNetworkChange = carrierNetworkChange, roaming = roaming, name = name, + slice = slice, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt index 8b03f71a2729..0aa95f8821cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt @@ -36,6 +36,7 @@ sealed interface FakeNetworkEventModel { val carrierNetworkChange: Boolean, val roaming: Boolean, val name: String, + val slice: Boolean = false, ) : FakeNetworkEventModel data class MobileDisabled( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt index 28be3be28928..27edd1ec0caa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt @@ -174,6 +174,13 @@ class CarrierMergedConnectionRepository( */ override val isAllowedDuringAirplaneMode = MutableStateFlow(true).asStateFlow() + /** + * It's not currently considered possible that a carrier merged network can have these + * prioritized capabilities. If we need to track them, we can add the same check as is in + * [MobileConnectionRepositoryImpl]. + */ + override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false).asStateFlow() + override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled companion object { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt index ee11c06ef3f5..6b6192186e0f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt @@ -309,6 +309,15 @@ class FullMobileConnectionRepository( activeRepo.value.isAllowedDuringAirplaneMode.value, ) + override val hasPrioritizedNetworkCapabilities = + activeRepo + .flatMapLatest { it.hasPrioritizedNetworkCapabilities } + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.hasPrioritizedNetworkCapabilities.value, + ) + class Factory @Inject constructor( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index dc50990d002a..760dd7eba3cf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -21,6 +21,11 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.net.ConnectivityManager +import android.net.ConnectivityManager.NetworkCallback +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN import android.telephony.CellSignalStrengthCdma import android.telephony.ServiceState @@ -91,6 +96,7 @@ class MobileConnectionRepositoryImpl( subscriptionModel: StateFlow<SubscriptionModel?>, defaultNetworkName: NetworkNameModel, networkNameSeparator: String, + connectivityManager: ConnectivityManager, private val telephonyManager: TelephonyManager, systemUiCarrierConfig: SystemUiCarrierConfig, broadcastDispatcher: BroadcastDispatcher, @@ -374,11 +380,50 @@ class MobileConnectionRepositoryImpl( /** Typical mobile connections aren't available during airplane mode. */ override val isAllowedDuringAirplaneMode = MutableStateFlow(false).asStateFlow() + /** + * Currently, a network with NET_CAPABILITY_PRIORITIZE_LATENCY is the only type of network that + * we consider to be a "network slice". _PRIORITIZE_BANDWIDTH may be added in the future. Any of + * these capabilities that are used here must also be represented in the + * self_certified_network_capabilities.xml config file + */ + @SuppressLint("WrongConstant") + private val networkSliceRequest = + NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY) + .setSubscriptionIds(setOf(subId)) + .build() + + @SuppressLint("MissingPermission") + override val hasPrioritizedNetworkCapabilities: StateFlow<Boolean> = + conflatedCallbackFlow { + // Our network callback listens only for this.subId && net_cap_prioritize_latency + // therefore our state is a simple mapping of whether or not that network exists + val callback = + object : NetworkCallback() { + override fun onAvailable(network: Network) { + logger.logPrioritizedNetworkAvailable(network.netId) + trySend(true) + } + + override fun onLost(network: Network) { + logger.logPrioritizedNetworkLost(network.netId) + trySend(false) + } + } + + connectivityManager.registerNetworkCallback(networkSliceRequest, callback) + + awaitClose { connectivityManager.unregisterNetworkCallback(callback) } + } + .flowOn(bgDispatcher) + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + class Factory @Inject constructor( private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, + private val connectivityManager: ConnectivityManager, private val telephonyManager: TelephonyManager, private val logger: MobileInputLogger, private val carrierConfigRepository: CarrierConfigRepository, @@ -399,6 +444,7 @@ class MobileConnectionRepositoryImpl( subscriptionModel, defaultNetworkName, networkNameSeparator, + connectivityManager, telephonyManager.createForSubscriptionId(subId), carrierConfigRepository.getOrCreateConfigForSubId(subId), broadcastDispatcher, @@ -421,11 +467,17 @@ private fun Intent.carrierId(): Int = */ sealed interface CallbackEvent { data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent + data class OnDataActivity(val direction: Int) : CallbackEvent + data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent + data class OnDataEnabledChanged(val enabled: Boolean) : CallbackEvent + data class OnDisplayInfoChanged(val telephonyDisplayInfo: TelephonyDisplayInfo) : CallbackEvent + data class OnServiceStateChanged(val serviceState: ServiceState) : CallbackEvent + data class OnSignalStrengthChanged(val signalStrength: SignalStrength) : CallbackEvent } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt index 812e91beee48..610fede3dfea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt @@ -60,6 +60,8 @@ class FakeMobileConnectionRepository( override val isAllowedDuringAirplaneMode = MutableStateFlow(false) + override val hasPrioritizedNetworkCapabilities = MutableStateFlow(false) + fun setDataEnabled(enabled: Boolean) { _dataEnabled.value = enabled } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index 57f97ec66a00..1f8cc54211e6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -123,6 +123,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange = testCase.carrierNetworkChange, roaming = testCase.roaming, name = "demo name", + slice = testCase.slice, ) fakeNetworkEventFlow.value = networkModel @@ -142,6 +143,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC launch { conn.carrierName.collect {} } launch { conn.isEmergencyOnly.collect {} } launch { conn.dataConnectionState.collect {} } + launch { conn.hasPrioritizedNetworkCapabilities.collect {} } } return job } @@ -165,6 +167,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC .isEqualTo(NetworkNameModel.IntentDerived(model.name)) assertThat(conn.carrierName.value) .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) + assertThat(conn.hasPrioritizedNetworkCapabilities.value).isEqualTo(model.slice) // TODO(b/261029387): check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() @@ -190,6 +193,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC val carrierNetworkChange: Boolean, val roaming: Boolean, val name: String, + val slice: Boolean, ) { override fun toString(): String { return "INPUT(level=$level, " + @@ -200,7 +204,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC "activity=$activity, " + "carrierNetworkChange=$carrierNetworkChange, " + "roaming=$roaming, " + - "name=$name)" + "name=$name," + + "slice=$slice)" } // Convenience for iterating test data and creating new cases @@ -214,6 +219,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange: Boolean? = null, roaming: Boolean? = null, name: String? = null, + slice: Boolean? = null, ): TestCase = TestCase( level = level ?: this.level, @@ -225,6 +231,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange = carrierNetworkChange ?: this.carrierNetworkChange, roaming = roaming ?: this.roaming, name = name ?: this.name, + slice = slice ?: this.slice, ) } @@ -254,6 +261,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC // 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") + private val slice = listOf(false, true) @Parameters(name = "{0}") @JvmStatic fun data() = testData() @@ -291,6 +299,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange.first(), roaming.first(), names.first(), + slice.first(), ) val tail = @@ -303,6 +312,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange.map { baseCase.modifiedBy(carrierNetworkChange = it) }, roaming.map { baseCase.modifiedBy(roaming = it) }, names.map { baseCase.modifiedBy(name = it) }, + slice.map { baseCase.modifiedBy(slice = it) } ) .flatten() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index 2712b70a9745..d918fa8193bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -549,6 +549,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { launch { conn.carrierName.collect {} } launch { conn.isEmergencyOnly.collect {} } launch { conn.dataConnectionState.collect {} } + launch { conn.hasPrioritizedNetworkCapabilities.collect {} } } return job } @@ -574,6 +575,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { .isEqualTo(NetworkNameModel.IntentDerived(model.name)) assertThat(conn.carrierName.value) .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) + assertThat(conn.hasPrioritizedNetworkCapabilities.value).isEqualTo(model.slice) // TODO(b/261029387) check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() @@ -599,6 +601,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(conn.isEmergencyOnly.value).isFalse() assertThat(conn.isGsm.value).isFalse() assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected) + assertThat(conn.hasPrioritizedNetworkCapabilities.value).isFalse() job.cancel() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt index ede02d1fbc9c..1c21ebe05d84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod +import android.net.ConnectivityManager import android.telephony.ServiceState import android.telephony.SignalStrength import android.telephony.TelephonyCallback @@ -80,6 +81,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { ) private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>() private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>() + private val connectivityManager = mock<ConnectivityManager>() private val subscriptionModel = MutableStateFlow( @@ -678,6 +680,7 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() { subscriptionModel, DEFAULT_NAME_MODEL, SEP, + connectivityManager, telephonyManager, systemUiCarrierConfig = mock(), fakeBroadcastDispatcher, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index 8ef82c9fe7bc..ba6426586ebd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.net.ConnectivityManager +import android.net.ConnectivityManager.NetworkCallback import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL @@ -85,7 +87,9 @@ import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityMod import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.mockito.withArgCaptor import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -107,6 +111,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { private lateinit var underTest: MobileConnectionRepositoryImpl private lateinit var connectionsRepo: FakeMobileConnectionsRepository + @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var telephonyManager: TelephonyManager @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var tableLogger: TableLogBuffer @@ -144,6 +149,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { subscriptionModel, DEFAULT_NAME_MODEL, SEP, + connectivityManager, telephonyManager, systemUiCarrierConfig, fakeBroadcastDispatcher, @@ -904,6 +910,45 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { assertThat(latest).isFalse() } + @Test + fun hasPrioritizedCaps_defaultFalse() { + assertThat(underTest.hasPrioritizedNetworkCapabilities.value).isFalse() + } + + @Test + fun hasPrioritizedCaps_trueWhenAvailable() = + testScope.runTest { + val latest by collectLastValue(underTest.hasPrioritizedNetworkCapabilities) + + val callback: NetworkCallback = + withArgCaptor<NetworkCallback> { + verify(connectivityManager).registerNetworkCallback(any(), capture()) + } + + callback.onAvailable(mock()) + + assertThat(latest).isTrue() + } + + @Test + fun hasPrioritizedCaps_becomesFalseWhenNetworkLost() = + testScope.runTest { + val latest by collectLastValue(underTest.hasPrioritizedNetworkCapabilities) + + val callback: NetworkCallback = + withArgCaptor<NetworkCallback> { + verify(connectivityManager).registerNetworkCallback(any(), capture()) + } + + callback.onAvailable(mock()) + + assertThat(latest).isTrue() + + callback.onLost(mock()) + + assertThat(latest).isFalse() + } + private inline fun <reified T> getTelephonyCallbackForType(): T { return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt index 852ed2054fcd..889f60a08766 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod +import android.net.ConnectivityManager import android.telephony.ServiceState import android.telephony.TelephonyCallback import android.telephony.TelephonyCallback.CarrierNetworkListener @@ -96,6 +97,7 @@ class MobileConnectionTelephonySmokeTests : SysuiTestCase() { private lateinit var underTest: MobileConnectionRepositoryImpl private lateinit var connectionsRepo: FakeMobileConnectionsRepository + @Mock private lateinit var connectivityManager: ConnectivityManager @Mock private lateinit var telephonyManager: TelephonyManager @Mock private lateinit var logger: MobileInputLogger @Mock private lateinit var tableLogger: TableLogBuffer @@ -129,6 +131,7 @@ class MobileConnectionTelephonySmokeTests : SysuiTestCase() { subscriptionModel, DEFAULT_NAME, SEP, + connectivityManager, telephonyManager, systemUiCarrierConfig, fakeBroadcastDispatcher, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt index 9148c7580296..18ba6c4f5d9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt @@ -180,6 +180,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() { MobileConnectionRepositoryImpl.Factory( context, fakeBroadcastDispatcher, + connectivityManager, telephonyManager = telephonyManager, bgDispatcher = dispatcher, logger = logger, -- GitLab