[Status bar] Take underlying networks into account for wifi.

Bug: 225902574
Test: atest ConnectivityRepositoryImplTest WifiRepositoryImplTest
MobileConnectionsRepositoryTest

Change-Id: Ie576d9ce4f6babf62ff231a4f7d769663348e977
This commit is contained in:
Caitlin Shkuratov
2023-03-28 18:33:15 +00:00
parent 0abe80aa7b
commit ca5ed2ceb0
5 changed files with 634 additions and 12 deletions

View File

@@ -44,11 +44,11 @@ import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnecti
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel.Ethernet
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel.Mobile
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel.Wifi
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
import com.android.systemui.tuner.TunerService
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -68,12 +68,12 @@ interface ConnectivityRepository {
val defaultConnections: StateFlow<DefaultConnectionModel>
}
@OptIn(ExperimentalCoroutinesApi::class)
@SuppressLint("MissingPermission")
@SysUISingleton
class ConnectivityRepositoryImpl
@Inject
constructor(
connectivityManager: ConnectivityManager,
private val connectivityManager: ConnectivityManager,
private val connectivitySlots: ConnectivitySlots,
context: Context,
dumpManager: DumpManager,
@@ -144,15 +144,14 @@ constructor(
) {
logger.logOnDefaultCapabilitiesChanged(network, networkCapabilities)
val wifiInfo =
networkCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
val isWifiDefault =
networkCapabilities.hasTransport(TRANSPORT_WIFI) ||
networkCapabilities.getMainOrUnderlyingWifiInfo() != null
networkCapabilities.hasTransport(TRANSPORT_WIFI) || wifiInfo != null
val isMobileDefault =
networkCapabilities.hasTransport(TRANSPORT_CELLULAR)
val isCarrierMergedDefault =
networkCapabilities
.getMainOrUnderlyingWifiInfo()
?.isCarrierMerged == true
val isCarrierMergedDefault = wifiInfo?.isCarrierMerged == true
val isEthernetDefault =
networkCapabilities.hasTransport(TRANSPORT_ETHERNET)
@@ -209,7 +208,32 @@ constructor(
* always use [WifiInfo] if it's available, so we need to check the underlying transport
* info.
*/
fun NetworkCapabilities.getMainOrUnderlyingWifiInfo(): WifiInfo? {
fun NetworkCapabilities.getMainOrUnderlyingWifiInfo(
connectivityManager: ConnectivityManager,
): WifiInfo? {
val mainWifiInfo = this.getMainWifiInfo()
if (mainWifiInfo != null) {
return mainWifiInfo
}
// Only CELLULAR networks may have underlying wifi information that's relevant to SysUI,
// so skip the underlying network check if it's not CELLULAR.
if (!this.hasTransport(TRANSPORT_CELLULAR)) {
return mainWifiInfo
}
// Some connections, like VPN connections, may have underlying networks that are
// eventually traced to a wifi or carrier merged connection. So, check those underlying
// networks for possible wifi information as well. See b/225902574.
return this.underlyingNetworks?.firstNotNullOfOrNull { underlyingNetwork ->
connectivityManager.getNetworkCapabilities(underlyingNetwork)?.getMainWifiInfo()
}
}
/**
* Checks the network capabilities for wifi info, but does *not* check the underlying
* networks. See [getMainOrUnderlyingWifiInfo].
*/
private fun NetworkCapabilities.getMainWifiInfo(): WifiInfo? {
// Wifi info can either come from a WIFI Transport, or from a CELLULAR transport for
// virtual networks like VCN.
val canHaveWifiInfo =

View File

@@ -138,7 +138,8 @@ constructor(
wifiNetworkChangeEvents.tryEmit(Unit)
val wifiInfo = networkCapabilities.getMainOrUnderlyingWifiInfo()
val wifiInfo =
networkCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
if (wifiInfo?.isPrimary == true) {
val wifiNetworkModel =
createWifiNetworkModel(

View File

@@ -75,6 +75,7 @@ import org.junit.Test
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -812,6 +813,79 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
job.cancel()
}
@Test
fun mobileIsDefault_isCarrierMergedViaUnderlyingWifi_isDefault() =
runBlocking(IMMEDIATE) {
var latest: Boolean? = null
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
val underlyingNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply {
whenever(this.isCarrierMerged).thenReturn(true)
}
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via WIFI
// transport and WifiInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN carrier merged is default, so mobile is default
assertThat(latest).isTrue()
job.cancel()
}
@Test
fun mobileIsDefault_isCarrierMergedViaUnderlyingCellular_isDefault() =
runBlocking(IMMEDIATE) {
var latest: Boolean? = null
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
}
whenever(
connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork)
)
.thenReturn(underlyingCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via CELLULAR
// transport and VcnTransportInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(listOf(underlyingCarrierMergedNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN carrier merged is default, so mobile is default
assertThat(latest).isTrue()
job.cancel()
}
@Test
fun mobileIsDefault_wifiDefault_mobileNotDefault() =
runBlocking(IMMEDIATE) {

View File

@@ -33,6 +33,7 @@ import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlo
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.DEFAULT_HIDDEN_ICONS_RESOURCE
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.HIDDEN_ICONS_TUNABLE_KEY
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -490,6 +491,111 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
@Test
fun defaultConnections_nullUnderlyingInfo_noError() {
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(null)
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// No assert, just verify no error
}
@Test
fun defaultConnections_underlyingInfoHasNullCapabilities_noError() {
val underlyingNetworkWithNull = mock<Network>()
whenever(connectivityManager.getNetworkCapabilities(underlyingNetworkWithNull))
.thenReturn(null)
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetworkWithNull))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// No assert, just verify no error
}
// This test verifies our internal API for completeness, but we don't expect this case to ever
// happen in practice.
@Test
fun defaultConnections_cellular_underlyingCarrierMergedViaWifi_allDefault() =
testScope.runTest {
var latest: DefaultConnectionModel? = null
val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
// Underlying carrier merged network
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
.thenReturn(underlyingCapabilities)
// Main network with underlying network
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(listOf(underlyingCarrierMergedNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
assertThat(latest!!.mobile.isDefault).isTrue()
assertThat(latest!!.carrierMerged.isDefault).isTrue()
assertThat(latest!!.wifi.isDefault).isTrue()
job.cancel()
}
/** Test for b/225902574. */
@Test
fun defaultConnections_cellular_underlyingCarrierMergedViaMobileWithVcnTransport_allDefault() =
testScope.runTest {
var latest: DefaultConnectionModel? = null
val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
// Underlying carrier merged network
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
}
whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
.thenReturn(underlyingCapabilities)
// Main network with underlying network
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(listOf(underlyingCarrierMergedNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
assertThat(latest!!.mobile.isDefault).isTrue()
assertThat(latest!!.carrierMerged.isDefault).isTrue()
assertThat(latest!!.wifi.isDefault).isTrue()
job.cancel()
}
@Test
fun defaultConnections_multipleTransports_multipleDefault() =
testScope.runTest {
@@ -548,6 +654,279 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
@Test
fun getMainOrUnderlyingWifiInfo_wifi_hasInfo() {
val wifiInfo = mock<WifiInfo>()
val capabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(wifiInfo)
}
val result = capabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
assertThat(result).isEqualTo(wifiInfo)
}
@Test
fun getMainOrUnderlyingWifiInfo_vcnWithWifi_hasInfo() {
val wifiInfo = mock<WifiInfo>()
val vcnInfo = VcnTransportInfo(wifiInfo)
val capabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(vcnInfo)
}
val result = capabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
assertThat(result).isEqualTo(wifiInfo)
}
@Test
fun getMainOrUnderlyingWifiInfo_notCellularOrWifiTransport_noInfo() {
val capabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
whenever(it.transportInfo).thenReturn(mock<WifiInfo>())
}
val result = capabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
assertThat(result).isNull()
}
@Test
fun getMainOrUnderlyingWifiInfo_cellular_underlyingWifi_hasInfo() {
val underlyingNetwork = mock<Network>()
val underlyingWifiInfo = mock<WifiInfo>()
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingWifiInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying wifi network
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN we fetch the underlying wifi info
assertThat(result).isEqualTo(underlyingWifiInfo)
}
@Test
fun getMainOrUnderlyingWifiInfo_notCellular_underlyingWifi_noInfo() {
val underlyingNetwork = mock<Network>()
val underlyingWifiInfo = mock<WifiInfo>()
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingWifiInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying wifi network but is *not* CELLULAR
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true)
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN we DON'T fetch the underlying wifi info
assertThat(result).isNull()
}
@Test
fun getMainOrUnderlyingWifiInfo_cellular_underlyingVcnWithWifi_hasInfo() {
val wifiInfo = mock<WifiInfo>()
val underlyingNetwork = mock<Network>()
val underlyingVcnInfo = VcnTransportInfo(wifiInfo)
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingVcnInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying VCN network with wifi
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN we fetch the wifi info
assertThat(result).isEqualTo(wifiInfo)
}
@Test
fun getMainOrUnderlyingWifiInfo_notCellular_underlyingVcnWithWifi_noInfo() {
val underlyingNetwork = mock<Network>()
val underlyingVcnInfo = VcnTransportInfo(mock<WifiInfo>())
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingVcnInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying wifi network but it is *not* CELLULAR
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true)
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN we DON'T fetch the underlying wifi info
assertThat(result).isNull()
}
@Test
fun getMainOrUnderlyingWifiInfo_cellular_underlyingCellularWithCarrierMerged_hasInfo() {
// Underlying carrier merged network
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
}
whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
.thenReturn(underlyingCapabilities)
// Main network with underlying network
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingCarrierMergedNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
assertThat(result).isEqualTo(carrierMergedInfo)
assertThat(result!!.isCarrierMerged).isTrue()
}
@Test
fun getMainOrUnderlyingWifiInfo_multipleUnderlying_usesFirstNonNull() {
// First underlying: Not wifi
val underlyingNotWifiNetwork = mock<Network>()
val underlyingNotWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
whenever(it.transportInfo).thenReturn(null)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNotWifiNetwork))
.thenReturn(underlyingNotWifiCapabilities)
// Second underlying: wifi
val underlyingWifiNetwork1 = mock<Network>()
val underlyingWifiInfo1 = mock<WifiInfo>()
val underlyingWifiCapabilities1 =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingWifiInfo1)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingWifiNetwork1))
.thenReturn(underlyingWifiCapabilities1)
// Third underlying: also wifi
val underlyingWifiNetwork2 = mock<Network>()
val underlyingWifiInfo2 = mock<WifiInfo>()
val underlyingWifiCapabilities2 =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(underlyingWifiInfo2)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingWifiNetwork2))
.thenReturn(underlyingWifiCapabilities2)
// WHEN the main capabilities has multiple underlying networks
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(
listOf(
underlyingNotWifiNetwork,
underlyingWifiNetwork1,
underlyingWifiNetwork2,
)
)
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN the first wifi one is used
assertThat(result).isEqualTo(underlyingWifiInfo1)
}
@Test
fun getMainOrUnderlyingWifiInfo_nestedUnderlying_doesNotLookAtNested() {
// WHEN there are two layers of underlying networks...
// Nested network
val nestedUnderlyingNetwork = mock<Network>()
val nestedWifiInfo = mock<WifiInfo>()
val nestedCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(nestedWifiInfo)
}
whenever(connectivityManager.getNetworkCapabilities(nestedUnderlyingNetwork))
.thenReturn(nestedCapabilities)
// Underlying network containing the nested network
val underlyingNetwork = mock<Network>()
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(nestedUnderlyingNetwork))
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingCapabilities)
// Main network containing the underlying network, which contains the nested network
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
val result = mainCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
// THEN only the first layer is checked, and the first layer has no wifi info
assertThat(result).isNull()
}
private fun createAndSetRepo() {
underTest =
ConnectivityRepositoryImpl(

View File

@@ -400,7 +400,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
fun wifiNetwork_cellularAndWifiTransports_usesCellular_isTrue() =
fun isWifiDefault_cellularAndWifiTransports_usesCellular_isTrue() =
runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
@@ -436,6 +436,75 @@ class WifiRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isWifiDefault_isCarrierMergedViaUnderlyingWifi_isTrue() =
runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
val underlyingNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply {
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
}
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via WIFI
// transport and WifiInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN the wifi network is carrier merged, so wifi is default
assertThat(underTest.isWifiDefault.value).isTrue()
job.cancel()
}
@Test
fun isWifiDefault_isCarrierMergedViaUnderlyingCellular_isTrue() =
runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
}
whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
.thenReturn(underlyingCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via CELLULAR
// transport and VcnTransportInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(listOf(underlyingCarrierMergedNetwork))
}
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN the wifi network is carrier merged, so wifi is default
assertThat(underTest.isWifiDefault.value).isTrue()
job.cancel()
}
@Test
fun isWifiDefault_wifiNetworkLost_isFalse() =
runBlocking(IMMEDIATE) {
@@ -510,6 +579,81 @@ class WifiRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
@Test
fun wifiNetwork_isCarrierMergedViaUnderlyingWifi_flowHasCarrierMerged() =
runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this)
val underlyingNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply {
whenever(this.isCarrierMerged).thenReturn(true)
whenever(this.isPrimary).thenReturn(true)
}
val underlyingWifiCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
}
whenever(connectivityManager.getNetworkCapabilities(underlyingNetwork))
.thenReturn(underlyingWifiCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via WIFI
// transport and WifiInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks).thenReturn(listOf(underlyingNetwork))
}
getNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN the wifi network is carrier merged
assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
job.cancel()
}
@Test
fun wifiNetwork_isCarrierMergedViaUnderlyingCellular_flowHasCarrierMerged() =
runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest.wifiNetwork.onEach { latest = it }.launchIn(this)
val underlyingCarrierMergedNetwork = mock<Network>()
val carrierMergedInfo =
mock<WifiInfo>().apply {
whenever(this.isCarrierMerged).thenReturn(true)
whenever(this.isPrimary).thenReturn(true)
}
val underlyingCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
}
whenever(connectivityManager.getNetworkCapabilities(underlyingCarrierMergedNetwork))
.thenReturn(underlyingCapabilities)
// WHEN the main capabilities have an underlying carrier merged network via CELLULAR
// transport and VcnTransportInfo
val mainCapabilities =
mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
whenever(it.transportInfo).thenReturn(null)
whenever(it.underlyingNetworks)
.thenReturn(listOf(underlyingCarrierMergedNetwork))
}
getNetworkCallback().onCapabilitiesChanged(NETWORK, mainCapabilities)
// THEN the wifi network is carrier merged
assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
job.cancel()
}
@Test
fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
runBlocking(IMMEDIATE) {