Merge changes I05fa65f3,Ie576d9ce into udc-dev
* changes: [SB Refactor] Use carrierMergedSubId for the mobile default calculation. [Status bar] Take underlying networks into account for wifi.
This commit is contained in:
committed by
Android (Google) Code Review
commit
b26dc33dda
@@ -60,6 +60,13 @@ interface MobileConnectionsRepository {
|
|||||||
*/
|
*/
|
||||||
val mobileIsDefault: StateFlow<Boolean>
|
val mobileIsDefault: StateFlow<Boolean>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the device currently has a carrier merged connection.
|
||||||
|
*
|
||||||
|
* See [CarrierMergedConnectionRepository] for more info.
|
||||||
|
*/
|
||||||
|
val hasCarrierMergedConnection: Flow<Boolean>
|
||||||
|
|
||||||
/** True if the default network connection is validated and false otherwise. */
|
/** True if the default network connection is validated and false otherwise. */
|
||||||
val defaultConnectionIsValidated: StateFlow<Boolean>
|
val defaultConnectionIsValidated: StateFlow<Boolean>
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,15 @@ constructor(
|
|||||||
.flatMapLatest { it.mobileIsDefault }
|
.flatMapLatest { it.mobileIsDefault }
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.mobileIsDefault.value)
|
.stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.mobileIsDefault.value)
|
||||||
|
|
||||||
|
override val hasCarrierMergedConnection: StateFlow<Boolean> =
|
||||||
|
activeRepo
|
||||||
|
.flatMapLatest { it.hasCarrierMergedConnection }
|
||||||
|
.stateIn(
|
||||||
|
scope,
|
||||||
|
SharingStarted.WhileSubscribed(),
|
||||||
|
realRepository.hasCarrierMergedConnection.value,
|
||||||
|
)
|
||||||
|
|
||||||
override val defaultConnectionIsValidated: StateFlow<Boolean> =
|
override val defaultConnectionIsValidated: StateFlow<Boolean> =
|
||||||
activeRepo
|
activeRepo
|
||||||
.flatMapLatest { it.defaultConnectionIsValidated }
|
.flatMapLatest { it.defaultConnectionIsValidated }
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ constructor(
|
|||||||
// TODO(b/261029387): not yet supported
|
// TODO(b/261029387): not yet supported
|
||||||
override val mobileIsDefault: StateFlow<Boolean> = MutableStateFlow(true)
|
override val mobileIsDefault: StateFlow<Boolean> = MutableStateFlow(true)
|
||||||
|
|
||||||
|
// TODO(b/261029387): not yet supported
|
||||||
|
override val hasCarrierMergedConnection = MutableStateFlow(false)
|
||||||
|
|
||||||
// TODO(b/261029387): not yet supported
|
// TODO(b/261029387): not yet supported
|
||||||
override val defaultConnectionIsValidated: StateFlow<Boolean> = MutableStateFlow(true)
|
override val defaultConnectionIsValidated: StateFlow<Boolean> = MutableStateFlow(true)
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -257,18 +258,32 @@ constructor(
|
|||||||
|
|
||||||
override val mobileIsDefault: StateFlow<Boolean> =
|
override val mobileIsDefault: StateFlow<Boolean> =
|
||||||
connectivityRepository.defaultConnections
|
connectivityRepository.defaultConnections
|
||||||
// Because carrier merged networks are displayed as mobile networks, they're
|
.map { it.mobile.isDefault }
|
||||||
// part of the `isDefault` calculation. See b/272586234.
|
|
||||||
.map { it.mobile.isDefault || it.carrierMerged.isDefault }
|
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.logDiffsForTable(
|
.logDiffsForTable(
|
||||||
tableLogger,
|
tableLogger,
|
||||||
columnPrefix = "",
|
columnPrefix = LOGGING_PREFIX,
|
||||||
columnName = "mobileIsDefault",
|
columnName = "mobileIsDefault",
|
||||||
initialValue = false,
|
initialValue = false,
|
||||||
)
|
)
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
|
override val hasCarrierMergedConnection: StateFlow<Boolean> =
|
||||||
|
combine(
|
||||||
|
connectivityRepository.defaultConnections,
|
||||||
|
carrierMergedSubId,
|
||||||
|
) { defaultConnections, carrierMergedSubId ->
|
||||||
|
defaultConnections.carrierMerged.isDefault || carrierMergedSubId != null
|
||||||
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
tableLogger,
|
||||||
|
columnPrefix = LOGGING_PREFIX,
|
||||||
|
columnName = "hasCarrierMergedConnection",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
override val defaultConnectionIsValidated: StateFlow<Boolean> =
|
override val defaultConnectionIsValidated: StateFlow<Boolean> =
|
||||||
connectivityRepository.defaultConnections
|
connectivityRepository.defaultConnections
|
||||||
.map { it.isValidated }
|
.map { it.isValidated }
|
||||||
|
|||||||
@@ -113,7 +113,22 @@ constructor(
|
|||||||
private val context: Context,
|
private val context: Context,
|
||||||
) : MobileIconsInteractor {
|
) : MobileIconsInteractor {
|
||||||
|
|
||||||
override val mobileIsDefault = mobileConnectionsRepo.mobileIsDefault
|
override val mobileIsDefault =
|
||||||
|
combine(
|
||||||
|
mobileConnectionsRepo.mobileIsDefault,
|
||||||
|
mobileConnectionsRepo.hasCarrierMergedConnection,
|
||||||
|
) { mobileIsDefault, hasCarrierMergedConnection ->
|
||||||
|
// Because carrier merged networks are displayed as mobile networks, they're part of
|
||||||
|
// the `isDefault` calculation. See b/272586234.
|
||||||
|
mobileIsDefault || hasCarrierMergedConnection
|
||||||
|
}
|
||||||
|
.logDiffsForTable(
|
||||||
|
tableLogger,
|
||||||
|
LOGGING_PREFIX,
|
||||||
|
columnName = "mobileIsDefault",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
override val activeDataConnectionHasDataEnabled: StateFlow<Boolean> =
|
override val activeDataConnectionHasDataEnabled: StateFlow<Boolean> =
|
||||||
mobileConnectionsRepo.activeMobileDataRepository
|
mobileConnectionsRepo.activeMobileDataRepository
|
||||||
|
|||||||
@@ -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.Ethernet
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel.Mobile
|
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.model.DefaultConnectionModel.Wifi
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
|
||||||
import com.android.systemui.tuner.TunerService
|
import com.android.systemui.tuner.TunerService
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -68,12 +68,12 @@ interface ConnectivityRepository {
|
|||||||
val defaultConnections: StateFlow<DefaultConnectionModel>
|
val defaultConnections: StateFlow<DefaultConnectionModel>
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@SuppressLint("MissingPermission")
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class ConnectivityRepositoryImpl
|
class ConnectivityRepositoryImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
connectivityManager: ConnectivityManager,
|
private val connectivityManager: ConnectivityManager,
|
||||||
private val connectivitySlots: ConnectivitySlots,
|
private val connectivitySlots: ConnectivitySlots,
|
||||||
context: Context,
|
context: Context,
|
||||||
dumpManager: DumpManager,
|
dumpManager: DumpManager,
|
||||||
@@ -144,15 +144,14 @@ constructor(
|
|||||||
) {
|
) {
|
||||||
logger.logOnDefaultCapabilitiesChanged(network, networkCapabilities)
|
logger.logOnDefaultCapabilitiesChanged(network, networkCapabilities)
|
||||||
|
|
||||||
|
val wifiInfo =
|
||||||
|
networkCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
|
||||||
|
|
||||||
val isWifiDefault =
|
val isWifiDefault =
|
||||||
networkCapabilities.hasTransport(TRANSPORT_WIFI) ||
|
networkCapabilities.hasTransport(TRANSPORT_WIFI) || wifiInfo != null
|
||||||
networkCapabilities.getMainOrUnderlyingWifiInfo() != null
|
|
||||||
val isMobileDefault =
|
val isMobileDefault =
|
||||||
networkCapabilities.hasTransport(TRANSPORT_CELLULAR)
|
networkCapabilities.hasTransport(TRANSPORT_CELLULAR)
|
||||||
val isCarrierMergedDefault =
|
val isCarrierMergedDefault = wifiInfo?.isCarrierMerged == true
|
||||||
networkCapabilities
|
|
||||||
.getMainOrUnderlyingWifiInfo()
|
|
||||||
?.isCarrierMerged == true
|
|
||||||
val isEthernetDefault =
|
val isEthernetDefault =
|
||||||
networkCapabilities.hasTransport(TRANSPORT_ETHERNET)
|
networkCapabilities.hasTransport(TRANSPORT_ETHERNET)
|
||||||
|
|
||||||
@@ -209,7 +208,32 @@ constructor(
|
|||||||
* always use [WifiInfo] if it's available, so we need to check the underlying transport
|
* always use [WifiInfo] if it's available, so we need to check the underlying transport
|
||||||
* info.
|
* 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
|
// Wifi info can either come from a WIFI Transport, or from a CELLULAR transport for
|
||||||
// virtual networks like VCN.
|
// virtual networks like VCN.
|
||||||
val canHaveWifiInfo =
|
val canHaveWifiInfo =
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ constructor(
|
|||||||
|
|
||||||
wifiNetworkChangeEvents.tryEmit(Unit)
|
wifiNetworkChangeEvents.tryEmit(Unit)
|
||||||
|
|
||||||
val wifiInfo = networkCapabilities.getMainOrUnderlyingWifiInfo()
|
val wifiInfo =
|
||||||
|
networkCapabilities.getMainOrUnderlyingWifiInfo(connectivityManager)
|
||||||
if (wifiInfo?.isPrimary == true) {
|
if (wifiInfo?.isPrimary == true) {
|
||||||
val wifiNetworkModel =
|
val wifiNetworkModel =
|
||||||
createWifiNetworkModel(
|
createWifiNetworkModel(
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ class FakeMobileConnectionsRepository(
|
|||||||
|
|
||||||
override val mobileIsDefault = MutableStateFlow(false)
|
override val mobileIsDefault = MutableStateFlow(false)
|
||||||
|
|
||||||
|
override val hasCarrierMergedConnection = MutableStateFlow(false)
|
||||||
|
|
||||||
override val defaultConnectionIsValidated = MutableStateFlow(false)
|
override val defaultConnectionIsValidated = MutableStateFlow(false)
|
||||||
|
|
||||||
private val subIdRepos = mutableMapOf<Int, MobileConnectionRepository>()
|
private val subIdRepos = mutableMapOf<Int, MobileConnectionRepository>()
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import kotlinx.coroutines.flow.filterNotNull
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertThrows
|
import org.junit.Assert.assertThrows
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
@@ -766,28 +767,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Regression test for b/272586234. */
|
|
||||||
@Test
|
|
||||||
fun mobileIsDefault_carrierMergedViaWifi_isDefault() =
|
|
||||||
runBlocking(IMMEDIATE) {
|
|
||||||
val carrierMergedInfo =
|
|
||||||
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
|
||||||
val caps =
|
|
||||||
mock<NetworkCapabilities>().also {
|
|
||||||
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
|
|
||||||
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
var latest: Boolean? = null
|
|
||||||
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
|
||||||
|
|
||||||
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
|
||||||
|
|
||||||
assertThat(latest).isTrue()
|
|
||||||
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun mobileIsDefault_carrierMergedViaMobile_isDefault() =
|
fun mobileIsDefault_carrierMergedViaMobile_isDefault() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
@@ -809,49 +788,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Regression test for b/272586234. */
|
|
||||||
@Test
|
|
||||||
fun mobileIsDefault_carrierMergedViaWifiWithVcnTransport_isDefault() =
|
|
||||||
runBlocking(IMMEDIATE) {
|
|
||||||
val carrierMergedInfo =
|
|
||||||
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
|
||||||
val caps =
|
|
||||||
mock<NetworkCapabilities>().also {
|
|
||||||
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
|
|
||||||
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
|
|
||||||
}
|
|
||||||
|
|
||||||
var latest: Boolean? = null
|
|
||||||
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
|
||||||
|
|
||||||
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
|
||||||
|
|
||||||
assertThat(latest).isTrue()
|
|
||||||
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun mobileIsDefault_carrierMergedViaMobileWithVcnTransport_isDefault() =
|
|
||||||
runBlocking(IMMEDIATE) {
|
|
||||||
val carrierMergedInfo =
|
|
||||||
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
|
||||||
val caps =
|
|
||||||
mock<NetworkCapabilities>().also {
|
|
||||||
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
|
|
||||||
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
|
|
||||||
}
|
|
||||||
|
|
||||||
var latest: Boolean? = null
|
|
||||||
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
|
||||||
|
|
||||||
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
|
||||||
|
|
||||||
assertThat(latest).isTrue()
|
|
||||||
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun mobileIsDefault_wifiDefault_mobileNotDefault() =
|
fun mobileIsDefault_wifiDefault_mobileNotDefault() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
@@ -888,6 +824,195 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Regression test for b/272586234. */
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_carrierMergedViaWifi_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val carrierMergedInfo =
|
||||||
|
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
||||||
|
val caps =
|
||||||
|
mock<NetworkCapabilities>().also {
|
||||||
|
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
|
||||||
|
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_carrierMergedViaMobile_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val carrierMergedInfo =
|
||||||
|
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
||||||
|
val caps =
|
||||||
|
mock<NetworkCapabilities>().also {
|
||||||
|
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
|
||||||
|
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Regression test for b/272586234. */
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_carrierMergedViaWifiWithVcnTransport_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val carrierMergedInfo =
|
||||||
|
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
||||||
|
val caps =
|
||||||
|
mock<NetworkCapabilities>().also {
|
||||||
|
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
|
||||||
|
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_carrierMergedViaMobileWithVcnTransport_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val carrierMergedInfo =
|
||||||
|
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
|
||||||
|
val caps =
|
||||||
|
mock<NetworkCapabilities>().also {
|
||||||
|
whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
|
||||||
|
whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_isCarrierMergedViaUnderlyingWifi_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.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)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
// THEN there's a carrier merged connection
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_isCarrierMergedViaUnderlyingCellular_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.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)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
// THEN there's a carrier merged connection
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Regression test for b/272586234. */
|
||||||
|
@Test
|
||||||
|
fun hasCarrierMergedConnection_defaultNotCarrierMerged_butWifiRepoHasCarrierMerged_isTrue() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.hasCarrierMergedConnection.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
// WHEN the default callback isn't carrier merged
|
||||||
|
val carrierMergedInfo =
|
||||||
|
mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(false) }
|
||||||
|
val caps =
|
||||||
|
mock<NetworkCapabilities>().also {
|
||||||
|
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
|
||||||
|
whenever(it.transportInfo).thenReturn(carrierMergedInfo)
|
||||||
|
}
|
||||||
|
getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
// BUT the wifi repo has gotten updates that it *is* carrier merged
|
||||||
|
wifiRepository.setWifiNetwork(WIFI_NETWORK_CM)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
// THEN hasCarrierMergedConnection is true
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun defaultConnectionIsValidated_startsAsFalse() {
|
fun defaultConnectionIsValidated_startsAsFalse() {
|
||||||
assertThat(underTest.defaultConnectionIsValidated.value).isFalse()
|
assertThat(underTest.defaultConnectionIsValidated.value).isFalse()
|
||||||
|
|||||||
@@ -456,7 +456,50 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun mobileIsDefault_usesRepoValue() =
|
fun mobileIsDefault_mobileFalseAndCarrierMergedFalse_false() =
|
||||||
|
testScope.runTest {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
connectionsRepository.mobileIsDefault.value = false
|
||||||
|
connectionsRepository.hasCarrierMergedConnection.value = false
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileIsDefault_mobileTrueAndCarrierMergedFalse_true() =
|
||||||
|
testScope.runTest {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
connectionsRepository.mobileIsDefault.value = true
|
||||||
|
connectionsRepository.hasCarrierMergedConnection.value = false
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Regression test for b/272586234. */
|
||||||
|
@Test
|
||||||
|
fun mobileIsDefault_mobileFalseAndCarrierMergedTrue_true() =
|
||||||
|
testScope.runTest {
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
connectionsRepository.mobileIsDefault.value = false
|
||||||
|
connectionsRepository.hasCarrierMergedConnection.value = true
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileIsDefault_updatesWhenRepoUpdates() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
var latest: Boolean? = null
|
var latest: Boolean? = null
|
||||||
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
|
||||||
@@ -467,7 +510,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
|||||||
connectionsRepository.mobileIsDefault.value = false
|
connectionsRepository.mobileIsDefault.value = false
|
||||||
assertThat(latest).isFalse()
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
connectionsRepository.mobileIsDefault.value = true
|
connectionsRepository.hasCarrierMergedConnection.value = true
|
||||||
assertThat(latest).isTrue()
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
job.cancel()
|
job.cancel()
|
||||||
|
|||||||
@@ -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.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.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.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.tuner.TunerService
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.argumentCaptor
|
import com.android.systemui.util.mockito.argumentCaptor
|
||||||
@@ -490,6 +491,111 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
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
|
@Test
|
||||||
fun defaultConnections_multipleTransports_multipleDefault() =
|
fun defaultConnections_multipleTransports_multipleDefault() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
@@ -548,6 +654,279 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
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() {
|
private fun createAndSetRepo() {
|
||||||
underTest =
|
underTest =
|
||||||
ConnectivityRepositoryImpl(
|
ConnectivityRepositoryImpl(
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun wifiNetwork_cellularAndWifiTransports_usesCellular_isTrue() =
|
fun isWifiDefault_cellularAndWifiTransports_usesCellular_isTrue() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
val job = underTest.isWifiDefault.launchIn(this)
|
val job = underTest.isWifiDefault.launchIn(this)
|
||||||
|
|
||||||
@@ -436,6 +436,75 @@ class WifiRepositoryImplTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
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
|
@Test
|
||||||
fun isWifiDefault_wifiNetworkLost_isFalse() =
|
fun isWifiDefault_wifiNetworkLost_isFalse() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
@@ -510,6 +579,81 @@ class WifiRepositoryImplTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
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
|
@Test
|
||||||
fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
|
fun wifiNetwork_carrierMergedButInvalidSubId_flowHasInvalid() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
|
|||||||
Reference in New Issue
Block a user