summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt110
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt107
10 files changed, 422 insertions, 43 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
index 7097568c4adf..e582a01ea88b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java
@@ -31,7 +31,7 @@ public class WifiIcons {
com.android.internal.R.drawable.ic_wifi_signal_4
};
- private static final int[] WIFI_NO_INTERNET_ICONS = {
+ public static final int[] WIFI_NO_INTERNET_ICONS = {
R.drawable.ic_no_internet_wifi_signal_0,
R.drawable.ic_no_internet_wifi_signal_1,
R.drawable.ic_no_internet_wifi_signal_2,
@@ -48,7 +48,7 @@ public class WifiIcons {
public static final int QS_WIFI_DISABLED = com.android.internal.R.drawable.ic_wifi_signal_0;
public static final int QS_WIFI_NO_NETWORK = com.android.internal.R.drawable.ic_wifi_signal_0;
- static final int WIFI_NO_NETWORK = QS_WIFI_NO_NETWORK;
+ public static final int WIFI_NO_NETWORK = QS_WIFI_NO_NETWORK;
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
index 5566fa6b5835..c96faabcda6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
@@ -16,13 +16,23 @@
package com.android.systemui.statusbar.pipeline.wifi.data.model
+import androidx.annotation.VisibleForTesting
+
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel {
/** A model representing that we have no active wifi network. */
object Inactive : WifiNetworkModel()
+ /**
+ * A model representing that our wifi network is actually a carrier merged network, meaning it's
+ * treated as more of a mobile network.
+ *
+ * See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
+ */
+ object CarrierMerged : WifiNetworkModel()
+
/** Provides information about an active wifi network. */
- class Active(
+ data class Active(
/**
* The [android.net.Network.netId] we received from
* [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
@@ -31,6 +41,19 @@ sealed class WifiNetworkModel {
*/
val networkId: Int,
+ /** See [android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED]. */
+ val isValidated: Boolean = false,
+
+ /**
+ * The wifi signal level, guaranteed to be 0 <= level <= 4.
+ *
+ * Null if we couldn't fetch the level for some reason.
+ *
+ * TODO(b/238425913): The level will only be null if we have a null WifiManager. Is there a
+ * way we can guarantee a non-null WifiManager?
+ */
+ val level: Int? = null,
+
/** See [android.net.wifi.WifiInfo.ssid]. */
val ssid: String? = null,
@@ -42,5 +65,18 @@ sealed class WifiNetworkModel {
/** See [android.net.wifi.WifiInfo.passpointProviderFriendlyName]. */
val passpointProviderFriendlyName: String? = null,
- ) : WifiNetworkModel()
+ ) : WifiNetworkModel() {
+ init {
+ require(level == null || level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
+ "0 <= wifi level <= 4 required; level was $level"
+ }
+ }
+
+ companion object {
+ @VisibleForTesting
+ internal const val MIN_VALID_LEVEL = 0
+ @VisibleForTesting
+ internal const val MAX_VALID_LEVEL = 4
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index 43fbabca823f..77654273bde4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -21,6 +21,7 @@ import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
@@ -31,6 +32,7 @@ import android.util.Log
import com.android.settingslib.Utils
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
@@ -38,10 +40,13 @@ import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.shareIn
/**
* Provides data related to the wifi state.
@@ -63,10 +68,11 @@ interface WifiRepository {
@SysUISingleton
@SuppressLint("MissingPermission")
class WifiRepositoryImpl @Inject constructor(
- connectivityManager: ConnectivityManager,
- wifiManager: WifiManager?,
- @Main mainExecutor: Executor,
- logger: ConnectivityPipelineLogger,
+ connectivityManager: ConnectivityManager,
+ logger: ConnectivityPipelineLogger,
+ @Main mainExecutor: Executor,
+ @Application scope: CoroutineScope,
+ wifiManager: WifiManager?,
) : WifiRepository {
override val wifiNetwork: Flow<WifiNetworkModel> = conflatedCallbackFlow {
var currentWifi: WifiNetworkModel = WIFI_NETWORK_DEFAULT
@@ -80,7 +86,12 @@ class WifiRepositoryImpl @Inject constructor(
val wifiInfo = networkCapabilitiesToWifiInfo(networkCapabilities)
if (wifiInfo?.isPrimary == true) {
- val wifiNetworkModel = wifiInfoToModel(wifiInfo, network.getNetId())
+ val wifiNetworkModel = createWifiNetworkModel(
+ wifiInfo,
+ network,
+ networkCapabilities,
+ wifiManager,
+ )
logger.logTransformation(
WIFI_NETWORK_CALLBACK_NAME,
oldValue = currentWifi,
@@ -112,6 +123,7 @@ class WifiRepositoryImpl @Inject constructor(
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}
+ .shareIn(scope, started = SharingStarted.WhileSubscribed())
override val wifiActivity: Flow<WifiActivityModel> =
if (wifiManager == null) {
@@ -164,14 +176,25 @@ class WifiRepositoryImpl @Inject constructor(
}
}
- private fun wifiInfoToModel(wifiInfo: WifiInfo, networkId: Int): WifiNetworkModel {
- return WifiNetworkModel.Active(
- networkId,
- wifiInfo.ssid,
- wifiInfo.isPasspointAp,
- wifiInfo.isOsuAp,
- wifiInfo.passpointProviderFriendlyName
- )
+ private fun createWifiNetworkModel(
+ wifiInfo: WifiInfo,
+ network: Network,
+ networkCapabilities: NetworkCapabilities,
+ wifiManager: WifiManager?,
+ ): WifiNetworkModel {
+ return if (wifiInfo.isCarrierMerged) {
+ WifiNetworkModel.CarrierMerged
+ } else {
+ WifiNetworkModel.Active(
+ network.getNetId(),
+ isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED),
+ level = wifiManager?.calculateSignalLevel(wifiInfo.rssi),
+ wifiInfo.ssid,
+ wifiInfo.isPasspointAp,
+ wifiInfo.isOsuAp,
+ wifiInfo.passpointProviderFriendlyName
+ )
+ }
}
private fun prettyPrintActivity(activity: Int): String {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
index a9da63b43aa4..afe19afff55f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
@@ -33,11 +33,12 @@ import kotlinx.coroutines.flow.map
*/
@SysUISingleton
class WifiInteractor @Inject constructor(
- repository: WifiRepository,
+ repository: WifiRepository,
) {
private val ssid: Flow<String?> = repository.wifiNetwork.map { info ->
when (info) {
is WifiNetworkModel.Inactive -> null
+ is WifiNetworkModel.CarrierMerged -> null
is WifiNetworkModel.Active -> when {
info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint ->
info.passpointProviderFriendlyName
@@ -47,6 +48,10 @@ class WifiInteractor @Inject constructor(
}
}
+ /** Our current wifi network. See [WifiNetworkModel]. */
+ val wifiNetwork: Flow<WifiNetworkModel> = repository.wifiNetwork
+
+ /** True if our wifi network has activity in (download), and false otherwise. */
val hasActivityIn: Flow<Boolean> = combine(repository.wifiActivity, ssid) { activity, ssid ->
activity.hasActivityIn && ssid != null
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index b06aaf441f5a..7607ddf4fe8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -25,10 +25,10 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.R
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
/**
@@ -50,11 +50,22 @@ object WifiViewBinder {
view.isVisible = true
iconView.isVisible = true
- iconView.setImageDrawable(view.context.getDrawable(WIFI_FULL_ICONS[2]))
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
+ viewModel.wifiIconResId.distinctUntilChanged().collect { iconResId ->
+ iconView.setImageDrawable(
+ if (iconResId != null && iconResId > 0) {
+ iconView.context.getDrawable(iconResId)
+ } else {
+ null
+ }
+ )
+ }
+ }
+
+ launch {
viewModel.tint.collect { tint ->
iconView.imageTintList = ColorStateList.valueOf(tint)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 7a262605681d..4fdcc44f1802 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -17,20 +17,24 @@
package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel
import android.graphics.Color
+import androidx.annotation.DrawableRes
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
/**
* Models the UI state for the status bar wifi icon.
- *
- * TODO(b/238425913): Hook this up to the real status bar wifi view using a view binder.
*/
class WifiViewModel @Inject constructor(
statusBarPipelineFlags: StatusBarPipelineFlags,
@@ -38,6 +42,23 @@ class WifiViewModel @Inject constructor(
private val logger: ConnectivityPipelineLogger,
private val interactor: WifiInteractor,
) {
+ /**
+ * The drawable resource ID to use for the wifi icon. Null if we shouldn't display any icon.
+ */
+ @DrawableRes
+ val wifiIconResId: Flow<Int?> = interactor.wifiNetwork.map {
+ when (it) {
+ is WifiNetworkModel.CarrierMerged -> null
+ is WifiNetworkModel.Inactive -> WIFI_NO_NETWORK
+ is WifiNetworkModel.Active ->
+ when {
+ it.level == null -> null
+ it.isValidated -> WIFI_FULL_ICONS[it.level]
+ else -> WIFI_NO_INTERNET_ICONS[it.level]
+ }
+ }
+ }
+
val isActivityInVisible: Flow<Boolean>
get() =
if (!constants.shouldShowActivityConfig) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
new file mode 100644
index 000000000000..3d29d2b2c3c8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModelTest.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.wifi.data.model
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MAX_VALID_LEVEL
+import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel.Active.Companion.MIN_VALID_LEVEL
+import org.junit.Test
+
+@SmallTest
+class WifiNetworkModelTest : SysuiTestCase() {
+ @Test
+ fun active_levelsInValidRange_noException() {
+ (MIN_VALID_LEVEL..MAX_VALID_LEVEL).forEach { level ->
+ WifiNetworkModel.Active(NETWORK_ID, level = level)
+ // No assert, just need no crash
+ }
+ }
+
+ @Test
+ fun active_levelNull_noException() {
+ WifiNetworkModel.Active(NETWORK_ID, level = null)
+ // No assert, just need no crash
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun active_levelNegative_exceptionThrown() {
+ WifiNetworkModel.Active(NETWORK_ID, level = MIN_VALID_LEVEL - 1)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun active_levelTooHigh_exceptionThrown() {
+ WifiNetworkModel.Active(NETWORK_ID, level = MAX_VALID_LEVEL + 1)
+ }
+
+ companion object {
+ private const val NETWORK_ID = 2
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
index d0a38084af76..982927148a2e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository
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_WIFI
import android.net.vcn.VcnTransportInfo
@@ -39,11 +40,14 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.Executor
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
@@ -61,20 +65,28 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var connectivityManager: ConnectivityManager
@Mock private lateinit var wifiManager: WifiManager
private lateinit var executor: Executor
+ private lateinit var scope: CoroutineScope
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
executor = FakeExecutor(FakeSystemClock())
+ scope = CoroutineScope(IMMEDIATE)
underTest = WifiRepositoryImpl(
connectivityManager,
- wifiManager,
- executor,
logger,
+ executor,
+ scope,
+ wifiManager,
)
}
+ @After
+ fun tearDown() {
+ scope.cancel()
+ }
+
@Test
fun wifiNetwork_initiallyGetsDefault() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
@@ -115,6 +127,61 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
+ fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val wifiInfo = mock<WifiInfo>().apply {
+ whenever(this.ssid).thenReturn(SSID)
+ whenever(this.isPrimary).thenReturn(true)
+ whenever(this.isCarrierMerged).thenReturn(true)
+ }
+
+ getNetworkCallback().onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
+
+ assertThat(latest is WifiNetworkModel.CarrierMerged).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiNetwork_notValidated_networkNotValidated() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = false)
+ )
+
+ assertThat((latest as WifiNetworkModel.Active).isValidated).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiNetwork_validated_networkValidated() = runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO, isValidated = true)
+ )
+
+ assertThat((latest as WifiNetworkModel.Active).isValidated).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
fun wifiNetwork_nonPrimaryWifiNetworkAdded_flowHasNoNetwork() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest
@@ -282,13 +349,14 @@ class WifiRepositoryImplTest : SysuiTestCase() {
.launchIn(this)
val wifiInfo = mock<WifiInfo>().apply {
- whenever(this.ssid).thenReturn(SSID)
- whenever(this.isPrimary).thenReturn(true)
- }
+ whenever(this.ssid).thenReturn(SSID)
+ whenever(this.isPrimary).thenReturn(true)
+ }
// Start with the original network
- getNetworkCallback()
- .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(wifiInfo))
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(wifiInfo, isValidated = true)
+ )
// WHEN we keep the same network ID but change the SSID
val newSsid = "CD"
@@ -297,14 +365,16 @@ class WifiRepositoryImplTest : SysuiTestCase() {
whenever(this.isPrimary).thenReturn(true)
}
- getNetworkCallback()
- .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(newWifiInfo))
+ getNetworkCallback().onCapabilitiesChanged(
+ NETWORK, createWifiNetworkCapabilities(newWifiInfo, isValidated = false)
+ )
// THEN we've updated to the new SSID
assertThat(latest is WifiNetworkModel.Active).isTrue()
val latestActive = latest as WifiNetworkModel.Active
assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
assertThat(latestActive.ssid).isEqualTo(newSsid)
+ assertThat(latestActive.isValidated).isFalse()
job.cancel()
}
@@ -406,10 +476,11 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiActivity_nullWifiManager_receivesDefault() = runBlocking(IMMEDIATE) {
underTest = WifiRepositoryImpl(
- connectivityManager,
- wifiManager = null,
- executor,
- logger,
+ connectivityManager,
+ logger,
+ executor,
+ scope,
+ wifiManager = null,
)
var latest: WifiActivityModel? = null
@@ -501,11 +572,16 @@ class WifiRepositoryImplTest : SysuiTestCase() {
return callbackCaptor.value!!
}
- private fun createWifiNetworkCapabilities(wifiInfo: WifiInfo) =
- mock<NetworkCapabilities>().apply {
- whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
- whenever(this.transportInfo).thenReturn(wifiInfo)
+ private fun createWifiNetworkCapabilities(
+ wifiInfo: WifiInfo,
+ isValidated: Boolean = true,
+ ): NetworkCapabilities {
+ return mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.transportInfo).thenReturn(wifiInfo)
+ whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(isValidated)
}
+ }
private companion object {
const val NETWORK_ID = 45
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
index 5f1b1dbb19dc..9d8b4bcabc8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
@@ -126,6 +126,38 @@ class WifiInteractorTest : SysuiTestCase() {
}
@Test
+ fun hasActivityIn_inactiveNetwork_outputsFalse() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Inactive)
+ repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true))
+
+ var latest: Boolean? = null
+ val job = underTest
+ .hasActivityIn
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
+ fun hasActivityIn_carrierMergedNetwork_outputsFalse() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
+ repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true))
+
+ var latest: Boolean? = null
+ val job = underTest
+ .hasActivityIn
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isFalse()
+
+ job.cancel()
+ }
+
+ @Test
fun hasActivityIn_multipleChanges_multipleOutputChanges() = runBlocking(IMMEDIATE) {
repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL)
@@ -159,6 +191,28 @@ class WifiInteractorTest : SysuiTestCase() {
job.cancel()
}
+ @Test
+ fun wifiNetwork_matchesRepoWifiNetwork() = runBlocking(IMMEDIATE) {
+ val wifiNetwork = WifiNetworkModel.Active(
+ networkId = 45,
+ isValidated = true,
+ level = 3,
+ ssid = "AB",
+ passpointProviderFriendlyName = "friendly"
+ )
+ repository.setWifiNetwork(wifiNetwork)
+
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(wifiNetwork)
+
+ job.cancel()
+ }
+
companion object {
val VALID_WIFI_NETWORK_MODEL = WifiNetworkModel.Active(networkId = 1, ssid = "AB")
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index c79073409883..f0a775b52297 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -18,6 +18,9 @@ package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
+import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiActivityModel
@@ -62,14 +65,103 @@ class WifiViewModelTest : SysuiTestCase() {
logger,
interactor
)
+ }
+
+ @Test
+ fun wifiIconResId_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Inactive)
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_NO_NETWORK)
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
- // Set up with a valid SSID
- repository.setWifiNetwork(WifiNetworkModel.Active(networkId = 1, ssid = "AB"))
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isNull()
+
+ job.cancel()
}
@Test
- fun activityInVisible_showActivityConfigFalse_receivesFalse() = runBlocking(IMMEDIATE) {
+ fun wifiIconResId_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) {
+ repository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null))
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isNull()
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_isActiveAndValidated_level1_outputsFull1Icon() = runBlocking(IMMEDIATE) {
+ val level = 1
+
+ repository.setWifiNetwork(
+ WifiNetworkModel.Active(
+ NETWORK_ID,
+ isValidated = true,
+ level = level
+ )
+ )
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_FULL_ICONS[level])
+
+ job.cancel()
+ }
+
+ @Test
+ fun wifiIconResId_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) {
+ val level = 4
+
+ repository.setWifiNetwork(
+ WifiNetworkModel.Active(
+ NETWORK_ID,
+ isValidated = false,
+ level = level
+ )
+ )
+
+ var latest: Int? = null
+ val job = underTest
+ .wifiIconResId
+ .onEach { latest = it }
+ .launchIn(this)
+
+ assertThat(latest).isEqualTo(WIFI_NO_INTERNET_ICONS[level])
+
+ job.cancel()
+ }
+
+ @Test
+ fun activityInVisible_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(false)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -86,6 +178,7 @@ class WifiViewModelTest : SysuiTestCase() {
@Test
fun activityInVisible_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(false)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -104,8 +197,9 @@ class WifiViewModelTest : SysuiTestCase() {
}
@Test
- fun activityInVisible_showActivityConfigTrue_receivesUpdate() = runBlocking(IMMEDIATE) {
+ fun activityInVisible_showActivityConfigTrue_outputsUpdate() = runBlocking(IMMEDIATE) {
whenever(constants.shouldShowActivityConfig).thenReturn(true)
+ repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
var latest: Boolean? = null
val job = underTest
@@ -122,6 +216,11 @@ class WifiViewModelTest : SysuiTestCase() {
job.cancel()
}
+
+ companion object {
+ private const val NETWORK_ID = 2
+ private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(NETWORK_ID, ssid = "AB")
+ }
}
private val IMMEDIATE = Dispatchers.Main.immediate