summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Caitlin Shkuratov <caitlinshk@google.com> 2023-03-20 17:49:05 +0000
committer Caitlin Shkuratov <caitlinshk@google.com> 2023-03-24 19:11:24 +0000
commit0202e4a3373d81f5742d34cd925749800194421b (patch)
treeb6e184804ba6ff2f7275607fe2eb686dbdefe0f9
parentae05dfe4d4b6a3d8ae0f80e452a11f8203d28716 (diff)
[SB Refactor] Define a `defaultConnections` flow in the shared repo.
This CL: (1) Updates the wifi and mobile repos to use this shared flow instead of defining their own default network callbacks. (2) Updates `MobileConnectionsRepoImpl.defaultMobileNetworkConnectivity` to have `isDefault = true` when mobile **or** carrier merged is the default connection. This is needed to fix b/272586234: since carrier merged is displayed as a mobile network, but we only display mobile network information if mobile is default, we need `isDefault` to be true even in the carrier merged case. Bug: 272586234 Test: all tests in statusbar.pipeline Test: manual: verify wifi icon still works and updates with normal wifi Test: unfortunately, it's prohibitively difficult to set up a valid carrier merged connection to test this, so I was not able to manually test carrier merged. I wrote extensive unit tests instead Change-Id: I7922b47547c3a4d186e78b76f7fae9cf3460d4d6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt87
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt114
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt81
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt145
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt344
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt83
14 files changed, 895 insertions, 232 deletions
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 73bf188857c9..68cbbceb056d 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
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.pipeline.mobile.data
-import android.net.Network
-import android.net.NetworkCapabilities
import android.telephony.ServiceState
import android.telephony.SignalStrength
import android.telephony.TelephonyDisplayInfo
@@ -27,7 +25,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.MobileInputLog
-import com.android.systemui.statusbar.pipeline.shared.LoggerHelper
import javax.inject.Inject
/** Logs for inputs into the mobile pipeline. */
@@ -37,24 +34,6 @@ class MobileInputLogger
constructor(
@MobileInputLog private val buffer: LogBuffer,
) {
- fun logOnCapabilitiesChanged(
- network: Network,
- networkCapabilities: NetworkCapabilities,
- isDefaultNetworkCallback: Boolean,
- ) {
- LoggerHelper.logOnCapabilitiesChanged(
- buffer,
- TAG,
- network,
- networkCapabilities,
- isDefaultNetworkCallback,
- )
- }
-
- fun logOnLost(network: Network, isDefaultNetworkCallback: Boolean) {
- LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback)
- }
-
fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
buffer.log(
TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index a6fa0c55888d..8c93bf7c2198 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -19,12 +19,6 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
import android.annotation.SuppressLint
import android.content.Context
import android.content.IntentFilter
-import android.net.ConnectivityManager
-import android.net.ConnectivityManager.NetworkCallback
-import android.net.Network
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
-import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
@@ -50,6 +44,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.util.kotlin.pairwise
@@ -79,7 +74,7 @@ import kotlinx.coroutines.withContext
class MobileConnectionsRepositoryImpl
@Inject
constructor(
- private val connectivityManager: ConnectivityManager,
+ connectivityRepository: ConnectivityRepository,
private val subscriptionManager: SubscriptionManager,
private val telephonyManager: TelephonyManager,
private val logger: MobileInputLogger,
@@ -260,50 +255,11 @@ constructor(
subIdRepositoryCache[subId]
?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it }
- @SuppressLint("MissingPermission")
- private val defaultMobileNetworkConnectivity: StateFlow<DefaultConnectionModel> =
- conflatedCallbackFlow {
- val callback =
- object : NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
- override fun onLost(network: Network) {
- logger.logOnLost(network, isDefaultNetworkCallback = true)
- trySend(
- DefaultConnectionModel(
- mobileIsDefault = false,
- defaultConnectionIsValidated = false,
- )
- )
- }
-
- override fun onCapabilitiesChanged(
- network: Network,
- caps: NetworkCapabilities
- ) {
- logger.logOnCapabilitiesChanged(
- network,
- caps,
- isDefaultNetworkCallback = true,
- )
- trySend(
- DefaultConnectionModel(
- mobileIsDefault = caps.hasTransport(TRANSPORT_CELLULAR),
- defaultConnectionIsValidated =
- caps.hasCapability(NET_CAPABILITY_VALIDATED),
- )
- )
- }
- }
-
- connectivityManager.registerDefaultNetworkCallback(callback)
-
- awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
- }
- .distinctUntilChanged()
- .stateIn(scope, SharingStarted.WhileSubscribed(), DefaultConnectionModel())
-
override val mobileIsDefault: StateFlow<Boolean> =
- defaultMobileNetworkConnectivity
- .map { it.mobileIsDefault }
+ connectivityRepository.defaultConnections
+ // Because carrier merged networks are displayed as mobile networks, they're
+ // part of the `isDefault` calculation. See b/272586234.
+ .map { it.mobile.isDefault || it.carrierMerged.isDefault }
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
@@ -314,8 +270,8 @@ constructor(
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val defaultConnectionIsValidated: StateFlow<Boolean> =
- defaultMobileNetworkConnectivity
- .map { it.defaultConnectionIsValidated }
+ connectivityRepository.defaultConnections
+ .map { it.isValidated }
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
@@ -407,11 +363,6 @@ constructor(
groupUuid = groupUuid,
)
- private data class DefaultConnectionModel(
- val mobileIsDefault: Boolean = false,
- val defaultConnectionIsValidated: Boolean = false,
- )
-
companion object {
private const val LOGGING_PREFIX = "Repo"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
index 95548b84f769..82492babba46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
@@ -16,10 +16,13 @@
package com.android.systemui.statusbar.pipeline.shared
+import android.net.Network
+import android.net.NetworkCapabilities
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.SharedConnectivityInputLog
+import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
import javax.inject.Inject
/** Logs for connectivity-related inputs that are shared across wifi, mobile, etc. */
@@ -32,6 +35,32 @@ constructor(
fun logTuningChanged(tuningList: String?) {
buffer.log(TAG, LogLevel.DEBUG, { str1 = tuningList }, { "onTuningChanged: $str1" })
}
+
+ fun logOnDefaultCapabilitiesChanged(
+ network: Network,
+ networkCapabilities: NetworkCapabilities,
+ ) {
+ LoggerHelper.logOnCapabilitiesChanged(
+ buffer,
+ TAG,
+ network,
+ networkCapabilities,
+ isDefaultNetworkCallback = true,
+ )
+ }
+
+ fun logOnDefaultLost(network: Network) {
+ LoggerHelper.logOnLost(buffer, TAG, network, isDefaultNetworkCallback = true)
+ }
+
+ fun logDefaultConnectionsChanged(model: DefaultConnectionModel) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ model::messageInitializer,
+ model::messagePrinter,
+ )
+ }
}
private const val TAG = "ConnectivityInputLogger"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt
new file mode 100644
index 000000000000..2a02687f0761
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.data.model
+
+import android.net.NetworkCapabilities
+import com.android.systemui.plugins.log.LogMessage
+
+/**
+ * A model for all of the current default connections(s).
+ *
+ * Uses different classes for each connection type to ensure type safety when setting the values.
+ *
+ * Important: We generally expect there to be only *one* default network at a time (with the
+ * exception of carrier merged). Specifically, we don't expect to ever have both wifi *and* cellular
+ * as default at the same time. However, the framework network callbacks don't provide any
+ * guarantees about why types of network could be default at the same time, so we don't enforce any
+ * guarantees on this class.
+ */
+data class DefaultConnectionModel(
+ /** Wifi's status as default or not. */
+ val wifi: Wifi = Wifi(isDefault = false),
+
+ /** Mobile's status as default or not. */
+ val mobile: Mobile = Mobile(isDefault = false),
+
+ /**
+ * True if the current default network represents a carrier merged network, and false otherwise.
+ * See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
+ *
+ * Important: A carrier merged network can come in as either a
+ * [NetworkCapabilities.TRANSPORT_CELLULAR] *or* as a [NetworkCapabilities.TRANSPORT_WIFI]. This
+ * means that when carrier merged is in effect, either:
+ * - [wifi] *and* [carrierMerged] will be marked as default; or
+ * - [mobile] *and* [carrierMerged] will be marked as default
+ *
+ * Specifically, [carrierMerged] will never be the *only* default connection.
+ */
+ val carrierMerged: CarrierMerged = CarrierMerged(isDefault = false),
+
+ /** Ethernet's status as default or not. */
+ val ethernet: Ethernet = Ethernet(isDefault = false),
+
+ /** True if the default connection is currently validated and false otherwise. */
+ val isValidated: Boolean = false,
+) {
+ data class Wifi(val isDefault: Boolean)
+ data class Mobile(val isDefault: Boolean)
+ data class CarrierMerged(val isDefault: Boolean)
+ data class Ethernet(val isDefault: Boolean)
+
+ /**
+ * Used in conjunction with [ConnectivityInputLogger] to log this class without calling
+ * [toString] on it.
+ *
+ * Be sure to change [messagePrinter] whenever this method is changed.
+ */
+ fun messageInitializer(message: LogMessage) {
+ message.bool1 = wifi.isDefault
+ message.bool2 = mobile.isDefault
+ message.bool3 = carrierMerged.isDefault
+ message.bool4 = ethernet.isDefault
+ message.int1 = if (isValidated) 1 else 0
+ }
+
+ fun messagePrinter(message: LogMessage): String {
+ return "DefaultConnectionModel(" +
+ "wifi.isDefault=${message.bool1}, " +
+ "mobile.isDefault=${message.bool2}, " +
+ "carrierMerged.isDefault=${message.bool3}, " +
+ "ethernet.isDefault=${message.bool4}, " +
+ "isValidated=${if (message.int1 == 1) "true" else "false"})"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
index 5d9ba018822d..6479f3d9f8a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
@@ -16,7 +16,17 @@
package com.android.systemui.statusbar.pipeline.shared.data.repository
+import android.annotation.SuppressLint
import android.content.Context
+import android.net.ConnectivityManager
+import android.net.Network
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.net.vcn.VcnTransportInfo
+import android.net.wifi.WifiInfo
import androidx.annotation.ArrayRes
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
@@ -29,6 +39,11 @@ import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
+import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
+import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel.CarrierMerged
+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.tuner.TunerService
import java.io.PrintWriter
import javax.inject.Inject
@@ -37,6 +52,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/**
@@ -46,6 +63,9 @@ import kotlinx.coroutines.flow.stateIn
interface ConnectivityRepository {
/** Observable for the current set of connectivity icons that should be force-hidden. */
val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>>
+
+ /** Observable for which connection(s) are currently default. */
+ val defaultConnections: StateFlow<DefaultConnectionModel>
}
@OptIn(ExperimentalCoroutinesApi::class)
@@ -53,6 +73,7 @@ interface ConnectivityRepository {
class ConnectivityRepositoryImpl
@Inject
constructor(
+ connectivityManager: ConnectivityManager,
private val connectivitySlots: ConnectivitySlots,
context: Context,
dumpManager: DumpManager,
@@ -61,7 +82,7 @@ constructor(
tunerService: TunerService,
) : ConnectivityRepository, Dumpable {
init {
- dumpManager.registerDumpable("ConnectivityRepository", this)
+ dumpManager.registerNormalDumpable("ConnectivityRepository", this)
}
// The default set of hidden icons to use if we don't get any from [TunerService].
@@ -97,6 +118,67 @@ constructor(
initialValue = defaultHiddenIcons
)
+ @SuppressLint("MissingPermission")
+ override val defaultConnections: StateFlow<DefaultConnectionModel> =
+ conflatedCallbackFlow {
+ val callback =
+ object : ConnectivityManager.NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
+ override fun onLost(network: Network) {
+ logger.logOnDefaultLost(network)
+ // The system no longer has a default network, so everything is
+ // non-default.
+ trySend(
+ DefaultConnectionModel(
+ Wifi(isDefault = false),
+ Mobile(isDefault = false),
+ CarrierMerged(isDefault = false),
+ Ethernet(isDefault = false),
+ isValidated = false,
+ )
+ )
+ }
+
+ override fun onCapabilitiesChanged(
+ network: Network,
+ networkCapabilities: NetworkCapabilities,
+ ) {
+ logger.logOnDefaultCapabilitiesChanged(network, networkCapabilities)
+
+ val isWifiDefault =
+ networkCapabilities.hasTransport(TRANSPORT_WIFI) ||
+ networkCapabilities.getMainOrUnderlyingWifiInfo() != null
+ val isMobileDefault =
+ networkCapabilities.hasTransport(TRANSPORT_CELLULAR)
+ val isCarrierMergedDefault =
+ networkCapabilities
+ .getMainOrUnderlyingWifiInfo()
+ ?.isCarrierMerged == true
+ val isEthernetDefault =
+ networkCapabilities.hasTransport(TRANSPORT_ETHERNET)
+
+ val isValidated =
+ networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)
+
+ trySend(
+ DefaultConnectionModel(
+ Wifi(isWifiDefault),
+ Mobile(isMobileDefault),
+ CarrierMerged(isCarrierMergedDefault),
+ Ethernet(isEthernetDefault),
+ isValidated,
+ )
+ )
+ }
+ }
+
+ connectivityManager.registerDefaultNetworkCallback(callback)
+
+ awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
+ }
+ .distinctUntilChanged()
+ .onEach { logger.logDefaultConnectionsChanged(it) }
+ .stateIn(scope, SharingStarted.Eagerly, DefaultConnectionModel())
+
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.apply { println("defaultHiddenIcons=$defaultHiddenIcons") }
}
@@ -116,5 +198,35 @@ constructor(
.mapNotNull { connectivitySlots.getSlotFromName(it) }
.toSet()
}
+
+ /**
+ * Returns a [WifiInfo] object from the capabilities if it has one, or null if there is no
+ * underlying wifi network.
+ *
+ * This will return a valid [WifiInfo] object if wifi is the main transport **or** wifi is
+ * an underlying transport. This is important for carrier merged networks, where the main
+ * transport info is *not* wifi, but the underlying transport info *is* wifi. We want to
+ * always use [WifiInfo] if it's available, so we need to check the underlying transport
+ * info.
+ */
+ fun NetworkCapabilities.getMainOrUnderlyingWifiInfo(): WifiInfo? {
+ // Wifi info can either come from a WIFI Transport, or from a CELLULAR transport for
+ // virtual networks like VCN.
+ val canHaveWifiInfo =
+ this.hasTransport(TRANSPORT_CELLULAR) || this.hasTransport(TRANSPORT_WIFI)
+ if (!canHaveWifiInfo) {
+ return null
+ }
+
+ return when (val currentTransportInfo = transportInfo) {
+ // This VcnTransportInfo logic is copied from
+ // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
+ // re-used because it makes the logic here clearer, and because the method will be
+ // removed once this pipeline is fully launched.
+ is VcnTransportInfo -> currentTransportInfo.wifiInfo
+ is WifiInfo -> currentTransportInfo
+ else -> null
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index b5e7b7a13505..f80aa688268f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -30,7 +30,6 @@ import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiManager.TrafficStateCallback
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import com.android.settingslib.Utils
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -41,6 +40,8 @@ import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toWifiDataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.getMainOrUnderlyingWifiInfo
import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
@@ -55,6 +56,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
@@ -70,6 +72,7 @@ class WifiRepositoryImpl
constructor(
broadcastDispatcher: BroadcastDispatcher,
connectivityManager: ConnectivityManager,
+ connectivityRepository: ConnectivityRepository,
logger: WifiInputLogger,
@WifiTableLog wifiTableLogBuffer: TableLogBuffer,
@Main mainExecutor: Executor,
@@ -105,39 +108,9 @@ constructor(
)
override val isWifiDefault: StateFlow<Boolean> =
- conflatedCallbackFlow {
- // Note: This callback doesn't do any logging because we already log every network
- // change in the [wifiNetwork] callback.
- val callback =
- object : ConnectivityManager.NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
- override fun onCapabilitiesChanged(
- network: Network,
- networkCapabilities: NetworkCapabilities
- ) {
- logger.logOnCapabilitiesChanged(
- network,
- networkCapabilities,
- isDefaultNetworkCallback = true,
- )
-
- // This method will always be called immediately after the network
- // becomes the default, in addition to any time the capabilities change
- // while the network is the default.
- // If this network is a wifi network, then wifi is the default network.
- trySend(isWifiNetwork(networkCapabilities))
- }
-
- override fun onLost(network: Network) {
- logger.logOnLost(network, isDefaultNetworkCallback = true)
- // The system no longer has a default network, so wifi is definitely not
- // default.
- trySend(false)
- }
- }
-
- connectivityManager.registerDefaultNetworkCallback(callback)
- awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
- }
+ connectivityRepository.defaultConnections
+ // TODO(b/274493701): Should wifi be considered default if it's carrier merged?
+ .map { it.wifi.isDefault || it.carrierMerged.isDefault }
.distinctUntilChanged()
.logDiffsForTable(
wifiTableLogBuffer,
@@ -165,7 +138,7 @@ constructor(
wifiNetworkChangeEvents.tryEmit(Unit)
- val wifiInfo = networkCapabilitiesToWifiInfo(networkCapabilities)
+ val wifiInfo = networkCapabilities.getMainOrUnderlyingWifiInfo()
if (wifiInfo?.isPrimary == true) {
val wifiNetworkModel =
createWifiNetworkModel(
@@ -248,34 +221,6 @@ constructor(
// NetworkCallback inside [wifiNetwork] for our wifi network information.
val WIFI_NETWORK_DEFAULT = WifiNetworkModel.Inactive
- private fun networkCapabilitiesToWifiInfo(
- networkCapabilities: NetworkCapabilities
- ): WifiInfo? {
- return when {
- networkCapabilities.hasTransport(TRANSPORT_CELLULAR) ->
- // Sometimes, cellular networks can act as wifi networks (known as VCN --
- // virtual carrier network). So, see if this cellular network has wifi info.
- Utils.tryGetWifiInfoForVcn(networkCapabilities)
- networkCapabilities.hasTransport(TRANSPORT_WIFI) ->
- if (networkCapabilities.transportInfo is WifiInfo) {
- networkCapabilities.transportInfo as WifiInfo
- } else {
- null
- }
- else -> null
- }
- }
-
- /** True if these capabilities represent a wifi network. */
- private fun isWifiNetwork(networkCapabilities: NetworkCapabilities): Boolean {
- return when {
- networkCapabilities.hasTransport(TRANSPORT_WIFI) -> true
- networkCapabilities.hasTransport(TRANSPORT_CELLULAR) ->
- Utils.tryGetWifiInfoForVcn(networkCapabilities) != null
- else -> false
- }
- }
-
private fun createWifiNetworkModel(
wifiInfo: WifiInfo,
network: Network,
@@ -337,6 +282,7 @@ constructor(
constructor(
private val broadcastDispatcher: BroadcastDispatcher,
private val connectivityManager: ConnectivityManager,
+ private val connectivityRepository: ConnectivityRepository,
private val logger: WifiInputLogger,
@WifiTableLog private val wifiTableLogBuffer: TableLogBuffer,
@Main private val mainExecutor: Executor,
@@ -346,6 +292,7 @@ constructor(
return WifiRepositoryImpl(
broadcastDispatcher,
connectivityManager,
+ connectivityRepository,
logger,
wifiTableLogBuffer,
mainExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
deleted file mode 100644
index 7c9351c8495d..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLoggerTest.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.mobile.data
-
-import android.net.Network
-import android.net.NetworkCapabilities
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogcatEchoTracker
-import com.google.common.truth.Truth.assertThat
-import java.io.PrintWriter
-import java.io.StringWriter
-import org.junit.Test
-import org.mockito.Mockito
-import org.mockito.Mockito.mock
-
-@SmallTest
-class MobileInputLoggerTest : SysuiTestCase() {
- private val buffer =
- LogBufferFactory(DumpManager(), mock(LogcatEchoTracker::class.java)).create("buffer", 10)
- private val logger = MobileInputLogger(buffer)
-
- @Test
- fun testLogNetworkCapsChange_bufferHasInfo() {
- logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true)
-
- val stringWriter = StringWriter()
- buffer.dump(PrintWriter(stringWriter), tailLength = 0)
- val actualString = stringWriter.toString()
-
- val expectedNetId = NET_1_ID.toString()
- val expectedCaps = NET_1_CAPS.toString()
-
- assertThat(actualString).contains("onDefaultCapabilitiesChanged")
- assertThat(actualString).contains(expectedNetId)
- assertThat(actualString).contains(expectedCaps)
- }
-
- @Test
- fun testLogOnLost_bufferHasNetIdOfLostNetwork() {
- logger.logOnLost(NET_1, isDefaultNetworkCallback = false)
-
- val stringWriter = StringWriter()
- buffer.dump(PrintWriter(stringWriter), tailLength = 0)
- val actualString = stringWriter.toString()
-
- val expectedNetId = NET_1_ID.toString()
-
- assertThat(actualString).contains("onLost")
- assertThat(actualString).contains(expectedNetId)
- }
-
- companion object {
- private const val NET_1_ID = 100
- private val NET_1 =
- com.android.systemui.util.mockito.mock<Network>().also {
- Mockito.`when`(it.getNetId()).thenReturn(NET_1_ID)
- }
- private val NET_1_CAPS =
- NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
- .build()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 07c8cee9a3d4..0b2028532307 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository
-import android.net.ConnectivityManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
@@ -35,6 +34,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.util.mockito.any
@@ -77,8 +78,8 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
private lateinit var wifiDataSource: DemoModeWifiDataSource
private lateinit var logFactory: TableLogBufferFactory
private lateinit var wifiRepository: FakeWifiRepository
+ private lateinit var connectivityRepository: ConnectivityRepository
- @Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var subscriptionManager: SubscriptionManager
@Mock private lateinit var telephonyManager: TelephonyManager
@Mock private lateinit var logger: MobileInputLogger
@@ -110,9 +111,11 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
}
wifiRepository = FakeWifiRepository()
+ connectivityRepository = FakeConnectivityRepository()
+
realRepo =
MobileConnectionsRepositoryImpl(
- connectivityManager,
+ connectivityRepository,
subscriptionManager,
telephonyManager,
logger,
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 742abc273c8d..d65277f37ec4 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
@@ -22,6 +22,10 @@ import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.net.vcn.VcnTransportInfo
+import android.net.wifi.WifiInfo
import android.os.ParcelUuid
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionInfo
@@ -43,6 +47,9 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierCon
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.util.mockito.any
@@ -80,6 +87,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
private lateinit var connectionFactory: MobileConnectionRepositoryImpl.Factory
private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
private lateinit var fullConnectionFactory: FullMobileConnectionRepository.Factory
+ private lateinit var connectivityRepository: ConnectivityRepository
private lateinit var wifiRepository: FakeWifiRepository
private lateinit var carrierConfigRepository: CarrierConfigRepository
@Mock private lateinit var connectivityManager: ConnectivityManager
@@ -120,6 +128,17 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
}
}
+ connectivityRepository =
+ ConnectivityRepositoryImpl(
+ connectivityManager,
+ ConnectivitySlots(context),
+ context,
+ mock(),
+ mock(),
+ scope,
+ mock(),
+ )
+
wifiRepository = FakeWifiRepository()
carrierConfigRepository =
@@ -158,7 +177,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
underTest =
MobileConnectionsRepositoryImpl(
- connectivityManager,
+ connectivityRepository,
subscriptionManager,
telephonyManager,
logger,
@@ -707,6 +726,128 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
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
+ fun mobileIsDefault_carrierMergedViaMobile_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(carrierMergedInfo)
+ }
+
+ var latest: Boolean? = null
+ val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+
+ assertThat(latest).isTrue()
+
+ 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
+ fun mobileIsDefault_wifiDefault_mobileNotDefault() =
+ runBlocking(IMMEDIATE) {
+ val caps =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ }
+
+ var latest: Boolean? = null
+ val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun mobileIsDefault_ethernetDefault_mobileNotDefault() =
+ runBlocking(IMMEDIATE) {
+ val caps =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true)
+ }
+
+ var latest: Boolean? = null
+ val job = underTest.mobileIsDefault.onEach { latest = it }.launchIn(this)
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, caps)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
@Test
fun defaultConnectionIsValidated_startsAsFalse() {
assertThat(underTest.defaultConnectionIsValidated.value).isFalse()
@@ -759,7 +900,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
// the resources and then re-create the repo.
underTest =
MobileConnectionsRepositoryImpl(
- connectivityManager,
+ connectivityRepository,
subscriptionManager,
telephonyManager,
logger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
new file mode 100644
index 000000000000..03cd94fa9d70
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.data.model
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.log.LogMessageImpl
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@SmallTest
+class DefaultConnectionModelTest : SysuiTestCase() {
+ @Test
+ fun messageInitializerAndPrinter_isValidatedFalse_hasCorrectInfo() {
+ val model =
+ DefaultConnectionModel(
+ DefaultConnectionModel.Wifi(isDefault = false),
+ DefaultConnectionModel.Mobile(isDefault = true),
+ DefaultConnectionModel.CarrierMerged(isDefault = true),
+ DefaultConnectionModel.Ethernet(isDefault = false),
+ isValidated = false,
+ )
+ val message = LogMessageImpl.create()
+
+ model.messageInitializer(message)
+ val messageString = model.messagePrinter(message)
+
+ assertThat(messageString).contains("wifi.isDefault=false")
+ assertThat(messageString).contains("mobile.isDefault=true")
+ assertThat(messageString).contains("carrierMerged.isDefault=true")
+ assertThat(messageString).contains("ethernet.isDefault=false")
+ assertThat(messageString).contains("isValidated=false")
+ }
+
+ @Test
+ fun messageInitializerAndPrinter_isValidatedTrue_hasCorrectInfo() {
+ val model =
+ DefaultConnectionModel(
+ DefaultConnectionModel.Wifi(isDefault = true),
+ DefaultConnectionModel.Mobile(isDefault = false),
+ DefaultConnectionModel.CarrierMerged(isDefault = false),
+ DefaultConnectionModel.Ethernet(isDefault = false),
+ isValidated = true,
+ )
+ val message = LogMessageImpl.create()
+
+ model.messageInitializer(message)
+ val messageString = model.messagePrinter(message)
+
+ assertThat(messageString).contains("wifi.isDefault=true")
+ assertThat(messageString).contains("mobile.isDefault=false")
+ assertThat(messageString).contains("carrierMerged.isDefault=false")
+ assertThat(messageString).contains("ethernet.isDefault=false")
+ assertThat(messageString).contains("isValidated=true")
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
index 46b751b60e15..87d4f5c618a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt
@@ -16,17 +16,27 @@
package com.android.systemui.statusbar.pipeline.shared.data.repository
+import android.net.ConnectivityManager
+import android.net.Network
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.net.vcn.VcnTransportInfo
+import android.net.wifi.WifiInfo
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
+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.tuner.TunerService
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -38,7 +48,7 @@ import kotlinx.coroutines.yield
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
-import org.mockito.Mockito
+import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -48,6 +58,7 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
private lateinit var underTest: ConnectivityRepositoryImpl
+ @Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var connectivitySlots: ConnectivitySlots
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var logger: ConnectivityInputLogger
@@ -220,9 +231,327 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
job2.cancel()
}
+ @Test
+ fun defaultConnections_noTransports_nothingIsDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.mobile.isDefault).isFalse()
+ assertThat(latest!!.wifi.isDefault).isFalse()
+ assertThat(latest!!.ethernet.isDefault).isFalse()
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_cellularTransport_mobileIsDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.mobile.isDefault).isTrue()
+ assertThat(latest!!.wifi.isDefault).isFalse()
+ assertThat(latest!!.ethernet.isDefault).isFalse()
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_wifiTransport_wifiIsDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.wifi.isDefault).isTrue()
+ assertThat(latest!!.ethernet.isDefault).isFalse()
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+ assertThat(latest!!.mobile.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_ethernetTransport_ethernetIsDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.ethernet.isDefault).isTrue()
+ assertThat(latest!!.wifi.isDefault).isFalse()
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+ assertThat(latest!!.mobile.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_carrierMergedViaWifi_wifiAndCarrierMergedDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(carrierMergedInfo)
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.wifi.isDefault).isTrue()
+ assertThat(latest!!.carrierMerged.isDefault).isTrue()
+ assertThat(latest!!.mobile.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_carrierMergedViaMobile_mobileCarrierMergedWifiDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(carrierMergedInfo)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.mobile.isDefault).isTrue()
+ assertThat(latest!!.carrierMerged.isDefault).isTrue()
+ assertThat(latest!!.wifi.isDefault).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_carrierMergedViaWifiWithVcnTransport_wifiAndCarrierMergedDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.wifi.isDefault).isTrue()
+ assertThat(latest!!.carrierMerged.isDefault).isTrue()
+ assertThat(latest!!.mobile.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_carrierMergedViaMobileWithVcnTransport_mobileCarrierMergedWifiDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(VcnTransportInfo(carrierMergedInfo))
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.mobile.isDefault).isTrue()
+ assertThat(latest!!.carrierMerged.isDefault).isTrue()
+ assertThat(latest!!.wifi.isDefault).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_notCarrierMergedViaWifi_carrierMergedNotDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(false) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(carrierMergedInfo)
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_notCarrierMergedViaMobile_carrierMergedNotDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(false) }
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(carrierMergedInfo)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.carrierMerged.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_transportInfoNotWifi_wifiNotDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.transportInfo).thenReturn(mock())
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.wifi.isDefault).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_multipleTransports_multipleDefault() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_ETHERNET)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.mobile.isDefault).isTrue()
+ assertThat(latest!!.ethernet.isDefault).isTrue()
+ assertThat(latest!!.wifi.isDefault).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_hasValidated_isValidatedTrue() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(true)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.isValidated).isTrue()
+ job.cancel()
+ }
+
+ @Test
+ fun defaultConnections_noValidated_isValidatedFalse() =
+ testScope.runTest {
+ var latest: DefaultConnectionModel? = null
+ val job = underTest.defaultConnections.onEach { latest = it }.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().also {
+ whenever(it.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
+ .thenReturn(false)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest!!.isValidated).isFalse()
+ job.cancel()
+ }
+
private fun createAndSetRepo() {
underTest =
ConnectivityRepositoryImpl(
+ connectivityManager,
connectivitySlots,
context,
dumpManager,
@@ -234,7 +563,7 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
private fun getTunable(): TunerService.Tunable {
val callbackCaptor = argumentCaptor<TunerService.Tunable>()
- Mockito.verify(tunerService).addTunable(callbackCaptor.capture(), any())
+ verify(tunerService).addTunable(callbackCaptor.capture(), any())
return callbackCaptor.value!!
}
@@ -245,9 +574,18 @@ class ConnectivityRepositoryImplTest : SysuiTestCase() {
whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(ConnectivitySlot.MOBILE)
}
- companion object {
+ private fun getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback {
+ val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>()
+ verify(connectivityManager).registerDefaultNetworkCallback(callbackCaptor.capture())
+ return callbackCaptor.value!!
+ }
+
+ private companion object {
private const val SLOT_ETHERNET = "ethernet"
private const val SLOT_WIFI = "wifi"
private const val SLOT_MOBILE = "mobile"
+
+ const val NETWORK_ID = 45
+ val NETWORK = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
index bd70034b13de..9e825b704851 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.shared.data.repository
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
+import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -26,6 +27,9 @@ class FakeConnectivityRepository : ConnectivityRepository {
MutableStateFlow(emptySet())
override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = _forceHiddenIcons
+ override val defaultConnections: StateFlow<DefaultConnectionModel> =
+ MutableStateFlow(DefaultConnectionModel())
+
fun setForceHiddenIcons(hiddenIcons: Set<ConnectivitySlot>) {
_forceHiddenIcons.value = hiddenIcons
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index 25678b0530f6..70d2d2b68460 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -23,6 +23,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
@@ -78,6 +79,7 @@ class WifiRepositorySwitcherTest : SysuiTestCase() {
WifiRepositoryImpl(
fakeBroadcastDispatcher,
connectivityManager,
+ FakeConnectivityRepository(),
logger,
tableLogger,
mainExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index c7b31bcf9a0c..f69e9a39909b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -34,7 +34,10 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiInputLogger
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -78,6 +81,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var wifiManager: WifiManager
private lateinit var executor: Executor
private lateinit var scope: CoroutineScope
+ private lateinit var connectivityRepository: ConnectivityRepository
@Before
fun setUp() {
@@ -93,6 +97,18 @@ class WifiRepositoryImplTest : SysuiTestCase() {
.thenReturn(flowOf(Unit))
executor = FakeExecutor(FakeSystemClock())
scope = CoroutineScope(IMMEDIATE)
+
+ connectivityRepository =
+ ConnectivityRepositoryImpl(
+ connectivityManager,
+ ConnectivitySlots(context),
+ context,
+ mock(),
+ mock(),
+ scope,
+ mock(),
+ )
+
underTest = createRepo()
}
@@ -302,13 +318,77 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun isWifiDefault_cellularVcnNetwork_isTrue() =
+ fun isWifiDefault_carrierMergedViaCellular_isTrue() =
runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+
val capabilities =
mock<NetworkCapabilities>().apply {
whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ whenever(this.transportInfo).thenReturn(carrierMergedInfo)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(underTest.isWifiDefault.value).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun isWifiDefault_carrierMergedViaCellular_withVcnTransport_isTrue() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().apply {
+ whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(underTest.isWifiDefault.value).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun isWifiDefault_carrierMergedViaWifi_isTrue() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val carrierMergedInfo =
+ mock<WifiInfo>().apply { whenever(this.isCarrierMerged).thenReturn(true) }
+
+ val capabilities =
+ mock<NetworkCapabilities>().apply {
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(this.transportInfo).thenReturn(carrierMergedInfo)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(underTest.isWifiDefault.value).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun isWifiDefault_carrierMergedViaWifi_withVcnTransport_isTrue() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val capabilities =
+ mock<NetworkCapabilities>().apply {
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
}
@@ -931,6 +1011,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
return WifiRepositoryImpl(
broadcastDispatcher,
connectivityManager,
+ connectivityRepository,
logger,
tableLogger,
executor,