[SB Refactor] Provide a disabled wifi repo if there's no wifi manager.

This allows WifiRepositoryImpl to use a non-null WifiManager, which
removes a lot of null checks throughout the pipeline.

Bug: 238425913
Test: verify wifi icon still works
Test: verify wifi demo mode still works
Test: verify that, when WifiManager is null, the wifi icon never shows
Test: all tests in statusbar.pipeline.wifi
Change-Id: I8de76ad554769e91f1612ddfb3e9fa6dfa9bc6ed
This commit is contained in:
Caitlin Shkuratov
2022-12-28 17:18:26 +00:00
parent b638b557b8
commit 4d313e1c16
15 changed files with 286 additions and 133 deletions

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.pipeline.dagger
import android.net.wifi.WifiManager
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.table.TableLogBuffer
@@ -35,8 +36,11 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxyImpl
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.RealWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.DisabledWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import dagger.Binds
@@ -78,9 +82,23 @@ abstract class StatusBarPipelineModule {
@ClassKey(MobileUiAdapter::class)
abstract fun bindFeature(impl: MobileUiAdapter): CoreStartable
@Module
companion object {
@JvmStatic
@Provides
@SysUISingleton
fun provideRealWifiRepository(
wifiManager: WifiManager?,
disabledWifiRepository: DisabledWifiRepository,
wifiRepositoryImplFactory: WifiRepositoryImpl.Factory,
): RealWifiRepository {
// If we have a null [WifiManager], then the wifi repository should be permanently
// disabled.
return if (wifiManager == null) {
disabledWifiRepository
} else {
wifiRepositoryImplFactory.create(wifiManager)
}
}
@Provides
@SysUISingleton
@WifiTableLog
@@ -88,7 +106,6 @@ abstract class StatusBarPipelineModule {
return factory.create("WifiTableLog", 100)
}
@JvmStatic
@Provides
@SysUISingleton
@AirplaneTableLog

View File

@@ -23,6 +23,33 @@ import com.android.systemui.log.table.Diffable
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
/**
* A model representing that we couldn't fetch any wifi information.
*
* This is only used with [DisabledWifiRepository], where [WifiManager] is null.
*/
object Unavailable : WifiNetworkModel() {
override fun toString() = "WifiNetwork.Unavailable"
override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
if (prevVal is Unavailable) {
return
}
logFull(row)
}
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_UNAVAILABLE)
row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
row.logChange(COL_VALIDATED, false)
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_SSID, null)
row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
row.logChange(COL_ONLINE_SIGN_UP, false)
row.logChange(COL_PASSPOINT_NAME, null)
}
}
/** A model representing that we have no active wifi network. */
object Inactive : WifiNetworkModel() {
override fun toString() = "WifiNetwork.Inactive"
@@ -87,13 +114,8 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
/**
* 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,
val level: Int,
/** See [android.net.wifi.WifiInfo.ssid]. */
val ssid: String? = null,
@@ -108,7 +130,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
val passpointProviderFriendlyName: String? = null,
) : WifiNetworkModel() {
init {
require(level == null || level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
require(level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
"0 <= wifi level <= 4 required; level was $level"
}
}
@@ -125,11 +147,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
row.logChange(COL_VALIDATED, isValidated)
}
if (prevVal !is Active || prevVal.level != level) {
if (level != null) {
row.logChange(COL_LEVEL, level)
} else {
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
}
row.logChange(COL_LEVEL, level)
}
if (prevVal !is Active || prevVal.ssid != ssid) {
row.logChange(COL_SSID, ssid)
@@ -190,6 +208,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
}
const val TYPE_CARRIER_MERGED = "CarrierMerged"
const val TYPE_UNAVAILABLE = "Unavailable"
const val TYPE_INACTIVE = "Inactive"
const val TYPE_ACTIVE = "Active"

View File

@@ -34,3 +34,13 @@ interface WifiRepository {
/** Observable for the current wifi network activity. */
val wifiActivity: StateFlow<DataActivityModel>
}
/**
* A no-op interface used for Dagger bindings.
*
* [WifiRepositorySwitcher] needs to inject the "real" wifi repository, which could either be the
* full [WifiRepositoryImpl] or just [DisabledWifiRepository]. Having this interface lets us bind
* [RealWifiRepository], and then [WifiRepositorySwitcher] will automatically get the correct real
* repository.
*/
interface RealWifiRepository : WifiRepository

View File

@@ -58,7 +58,7 @@ import kotlinx.coroutines.flow.stateIn
class WifiRepositorySwitcher
@Inject
constructor(
private val realImpl: WifiRepositoryImpl,
private val realImpl: RealWifiRepository,
private val demoImpl: DemoWifiRepository,
private val demoModeController: DemoModeController,
@Application scope: CoroutineScope,

View File

@@ -89,7 +89,7 @@ constructor(
WifiNetworkModel.Active(
networkId = DEMO_NET_ID,
isValidated = validated ?: true,
level = level,
level = level ?: 0,
ssid = ssid,
// These fields below aren't supported in demo mode, since they aren't needed to satisfy

View File

@@ -0,0 +1,49 @@
/*
* 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.repository.prod
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/**
* Implementation of wifi repository used when wifi is permanently disabled on the device.
*
* This repo should only exist when [WifiManager] is null, which means that we can never fetch any
* wifi information.
*/
@SysUISingleton
class DisabledWifiRepository @Inject constructor() : RealWifiRepository {
override val isWifiEnabled: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
override val isWifiDefault: StateFlow<Boolean> = MutableStateFlow(false).asStateFlow()
override val wifiNetwork: StateFlow<WifiNetworkModel> = MutableStateFlow(NETWORK).asStateFlow()
override val wifiActivity: StateFlow<DataActivityModel> =
MutableStateFlow(ACTIVITY).asStateFlow()
companion object {
private val NETWORK = WifiNetworkModel.Unavailable
private val ACTIVITY = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
}
}

View File

@@ -29,7 +29,6 @@ import android.net.NetworkRequest
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.net.wifi.WifiManager.TrafficStateCallback
import android.util.Log
import com.android.settingslib.Utils
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -40,11 +39,11 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
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.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.RealWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -53,12 +52,9 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.stateIn
@@ -75,8 +71,8 @@ class WifiRepositoryImpl @Inject constructor(
@WifiTableLog wifiTableLogBuffer: TableLogBuffer,
@Main mainExecutor: Executor,
@Application scope: CoroutineScope,
wifiManager: WifiManager?,
) : WifiRepository {
wifiManager: WifiManager,
) : RealWifiRepository {
private val wifiStateChangeEvents: Flow<Unit> = broadcastDispatcher.broadcastFlow(
IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)
@@ -86,28 +82,24 @@ class WifiRepositoryImpl @Inject constructor(
private val wifiNetworkChangeEvents: MutableSharedFlow<Unit> =
MutableSharedFlow(extraBufferCapacity = 1)
// Because [WifiManager] doesn't expose a wifi enabled change listener, we do it
// internally by fetching [WifiManager.isWifiEnabled] whenever we think the state may
// have changed.
override val isWifiEnabled: StateFlow<Boolean> =
if (wifiManager == null) {
MutableStateFlow(false).asStateFlow()
} else {
// Because [WifiManager] doesn't expose a wifi enabled change listener, we do it
// internally by fetching [WifiManager.isWifiEnabled] whenever we think the state may
// have changed.
merge(wifiNetworkChangeEvents, wifiStateChangeEvents)
.mapLatest { wifiManager.isWifiEnabled }
.distinctUntilChanged()
.logDiffsForTable(
wifiTableLogBuffer,
columnPrefix = "",
columnName = "isWifiEnabled",
initialValue = wifiManager.isWifiEnabled,
)
.stateIn(
scope = scope,
started = SharingStarted.WhileSubscribed(),
initialValue = wifiManager.isWifiEnabled
)
}
merge(wifiNetworkChangeEvents, wifiStateChangeEvents)
.mapLatest { wifiManager.isWifiEnabled }
.distinctUntilChanged()
.logDiffsForTable(
wifiTableLogBuffer,
columnPrefix = "",
columnName = "isWifiEnabled",
initialValue = wifiManager.isWifiEnabled,
)
.stateIn(
scope = scope,
started = SharingStarted.WhileSubscribed(),
initialValue = wifiManager.isWifiEnabled,
)
override val isWifiDefault: StateFlow<Boolean> = conflatedCallbackFlow {
// Note: This callback doesn't do any logging because we already log every network change
@@ -217,29 +209,24 @@ class WifiRepositoryImpl @Inject constructor(
)
override val wifiActivity: StateFlow<DataActivityModel> =
if (wifiManager == null) {
Log.w(SB_LOGGING_TAG, "Null WifiManager; skipping activity callback")
flowOf(ACTIVITY_DEFAULT)
} else {
conflatedCallbackFlow {
val callback = TrafficStateCallback { state ->
logger.logInputChange("onTrafficStateChange", prettyPrintActivity(state))
trySend(state.toWifiDataActivityModel())
}
wifiManager.registerTrafficStateCallback(mainExecutor, callback)
awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
conflatedCallbackFlow {
val callback = TrafficStateCallback { state ->
logger.logInputChange("onTrafficStateChange", prettyPrintActivity(state))
trySend(state.toWifiDataActivityModel())
}
wifiManager.registerTrafficStateCallback(mainExecutor, callback)
awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
}
.logDiffsForTable(
wifiTableLogBuffer,
columnPrefix = ACTIVITY_PREFIX,
initialValue = ACTIVITY_DEFAULT,
)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
initialValue = ACTIVITY_DEFAULT
)
.logDiffsForTable(
wifiTableLogBuffer,
columnPrefix = ACTIVITY_PREFIX,
initialValue = ACTIVITY_DEFAULT,
)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
initialValue = ACTIVITY_DEFAULT,
)
companion object {
private const val ACTIVITY_PREFIX = "wifiActivity"
@@ -271,19 +258,19 @@ class WifiRepositoryImpl @Inject constructor(
wifiInfo: WifiInfo,
network: Network,
networkCapabilities: NetworkCapabilities,
wifiManager: WifiManager?,
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
network.getNetId(),
isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED),
level = wifiManager.calculateSignalLevel(wifiInfo.rssi),
wifiInfo.ssid,
wifiInfo.isPasspointAp,
wifiInfo.isOsuAp,
wifiInfo.passpointProviderFriendlyName
)
}
}
@@ -308,4 +295,28 @@ class WifiRepositoryImpl @Inject constructor(
private const val WIFI_NETWORK_CALLBACK_NAME = "wifiNetworkModel"
}
@SysUISingleton
class Factory
@Inject
constructor(
private val broadcastDispatcher: BroadcastDispatcher,
private val connectivityManager: ConnectivityManager,
private val logger: ConnectivityPipelineLogger,
@WifiTableLog private val wifiTableLogBuffer: TableLogBuffer,
@Main private val mainExecutor: Executor,
@Application private val scope: CoroutineScope,
) {
fun create(wifiManager: WifiManager): WifiRepositoryImpl {
return WifiRepositoryImpl(
broadcastDispatcher,
connectivityManager,
logger,
wifiTableLogBuffer,
mainExecutor,
scope,
wifiManager,
)
}
}
}

View File

@@ -65,6 +65,7 @@ class WifiInteractorImpl @Inject constructor(
override val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info ->
when (info) {
is WifiNetworkModel.Unavailable -> null
is WifiNetworkModel.Inactive -> null
is WifiNetworkModel.CarrierMerged -> null
is WifiNetworkModel.Active -> when {

View File

@@ -82,6 +82,7 @@ constructor(
/** Returns the icon to use based on the given network. */
private fun WifiNetworkModel.icon(): WifiIcon {
return when (this) {
is WifiNetworkModel.Unavailable -> WifiIcon.Hidden
is WifiNetworkModel.CarrierMerged -> WifiIcon.Hidden
is WifiNetworkModel.Inactive -> WifiIcon.Visible(
res = WIFI_NO_NETWORK,
@@ -89,27 +90,23 @@ constructor(
"${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}"
)
)
is WifiNetworkModel.Active ->
when (this.level) {
null -> WifiIcon.Hidden
else -> {
val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level])
when {
this.isValidated ->
WifiIcon.Visible(
WIFI_FULL_ICONS[this.level],
ContentDescription.Loaded(levelDesc)
)
else ->
WifiIcon.Visible(
WIFI_NO_INTERNET_ICONS[this.level],
ContentDescription.Loaded(
"$levelDesc,${context.getString(NO_INTERNET)}"
)
)
}
}
is WifiNetworkModel.Active -> {
val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level])
when {
this.isValidated ->
WifiIcon.Visible(
WIFI_FULL_ICONS[this.level],
ContentDescription.Loaded(levelDesc),
)
else ->
WifiIcon.Visible(
WIFI_NO_INTERNET_ICONS[this.level],
ContentDescription.Loaded(
"$levelDesc,${context.getString(NO_INTERNET)}"
),
)
}
}
}
}

View File

@@ -34,12 +34,6 @@ class WifiNetworkModelTest : SysuiTestCase() {
}
}
@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)

View File

@@ -0,0 +1,57 @@
/*
* 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.repository.prod
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@SmallTest
class DisabledWifiRepositoryTest : SysuiTestCase() {
private lateinit var underTest: DisabledWifiRepository
@Before
fun setUp() {
underTest = DisabledWifiRepository()
}
@Test
fun enabled_alwaysFalse() {
assertThat(underTest.isWifiEnabled.value).isEqualTo(false)
}
@Test
fun default_alwaysFalse() {
assertThat(underTest.isWifiDefault.value).isEqualTo(false)
}
@Test
fun network_alwaysUnavailable() {
assertThat(underTest.wifiNetwork.value).isEqualTo(WifiNetworkModel.Unavailable)
}
@Test
fun activity_alwaysFalse() {
assertThat(underTest.wifiActivity.value)
.isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
}
}

View File

@@ -33,7 +33,6 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.ACTIVITY_DEFAULT
import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
@@ -97,13 +96,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
scope.cancel()
}
@Test
fun isWifiEnabled_nullWifiManager_getsFalse() = runBlocking(IMMEDIATE) {
underTest = createRepo(wifiManagerToUse = null)
assertThat(underTest.isWifiEnabled.value).isFalse()
}
@Test
fun isWifiEnabled_initiallyGetsWifiManagerValue() = runBlocking(IMMEDIATE) {
whenever(wifiManager.isWifiEnabled).thenReturn(true)
@@ -720,21 +712,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
job2.cancel()
}
@Test
fun wifiActivity_nullWifiManager_receivesDefault() = runBlocking(IMMEDIATE) {
underTest = createRepo(wifiManagerToUse = null)
var latest: DataActivityModel? = null
val job = underTest
.wifiActivity
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isEqualTo(ACTIVITY_DEFAULT)
job.cancel()
}
@Test
fun wifiActivity_callbackGivesNone_activityFlowHasNone() = runBlocking(IMMEDIATE) {
var latest: DataActivityModel? = null
@@ -801,7 +778,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
private fun createRepo(wifiManagerToUse: WifiManager? = wifiManager): WifiRepositoryImpl {
private fun createRepo(): WifiRepositoryImpl {
return WifiRepositoryImpl(
broadcastDispatcher,
connectivityManager,
@@ -809,7 +786,7 @@ class WifiRepositoryImplTest : SysuiTestCase() {
tableLogger,
executor,
scope,
wifiManagerToUse,
wifiManager,
)
}

View File

@@ -51,6 +51,22 @@ class WifiInteractorImplTest : SysuiTestCase() {
underTest = WifiInteractorImpl(connectivityRepository, wifiRepository)
}
@Test
fun ssid_unavailableNetwork_outputsNull() =
runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Unavailable)
var latest: String? = "default"
val job = underTest
.ssid
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isNull()
job.cancel()
}
@Test
fun ssid_inactiveNetwork_outputsNull() = runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
@@ -85,6 +101,7 @@ class WifiInteractorImplTest : SysuiTestCase() {
fun ssid_isPasspointAccessPoint_outputsPasspointName() = runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(
networkId = 1,
level = 1,
isPasspointAccessPoint = true,
passpointProviderFriendlyName = "friendly",
))
@@ -104,6 +121,7 @@ class WifiInteractorImplTest : SysuiTestCase() {
fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() = runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(
networkId = 1,
level = 1,
isOnlineSignUpForPasspointAccessPoint = true,
passpointProviderFriendlyName = "friendly",
))
@@ -123,6 +141,7 @@ class WifiInteractorImplTest : SysuiTestCase() {
fun ssid_unknownSsid_outputsNull() = runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(
networkId = 1,
level = 1,
ssid = WifiManager.UNKNOWN_SSID,
))
@@ -141,6 +160,7 @@ class WifiInteractorImplTest : SysuiTestCase() {
fun ssid_validSsid_outputsSsid() = runBlocking(IMMEDIATE) {
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(
networkId = 1,
level = 1,
ssid = "MyAwesomeWifiNetwork",
))

View File

@@ -379,6 +379,12 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
expected = null,
),
// network = Unavailable => not shown
TestCase(
network = WifiNetworkModel.Unavailable,
expected = null,
),
// network = Active & validated = false => not shown
TestCase(
network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
@@ -397,12 +403,6 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
description = "Full internet level 4 icon",
),
),
// network has null level => not shown
TestCase(
network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = null),
expected = null,
),
)
}
}

View File

@@ -228,7 +228,7 @@ class WifiViewModelTest : SysuiTestCase() {
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null))
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1))
var activityIn: Boolean? = null
val activityInJob = underTest
@@ -553,7 +553,8 @@ class WifiViewModelTest : SysuiTestCase() {
companion object {
private const val NETWORK_ID = 2
private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(NETWORK_ID, ssid = "AB")
private val ACTIVE_VALID_WIFI_NETWORK =
WifiNetworkModel.Active(NETWORK_ID, ssid = "AB", level = 1)
}
}