Merge "[Status Bar] Allow carrier merged to be displayed even in airplane mode." into udc-qpr-dev

This commit is contained in:
Caitlin Shkuratov
2023-08-07 14:33:01 +00:00
committed by Android (Google) Code Review
14 changed files with 123 additions and 5 deletions

View File

@@ -118,6 +118,11 @@ interface MobileConnectionRepository {
/** The service provider name for this network connection, or the default name */
val networkName: StateFlow<NetworkNameModel>
/**
* True if this type of connection is allowed while airplane mode is on, and false otherwise.
*/
val isAllowedDuringAirplaneMode: StateFlow<Boolean>
companion object {
/** The default number of levels to use for [numberOfLevels]. */
const val DEFAULT_NUM_LEVELS = 4

View File

@@ -186,6 +186,8 @@ class DemoMobileConnectionRepository(
override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
/**
* Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
* from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
@@ -217,6 +219,8 @@ class DemoMobileConnectionRepository(
(event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
_carrierNetworkChangeActive.value = event.carrierNetworkChange
_resolvedNetworkType.value = resolvedNetworkType
isAllowedDuringAirplaneMode.value = false
}
fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
@@ -240,6 +244,7 @@ class DemoMobileConnectionRepository(
_isInService.value = true
_isGsm.value = false
_carrierNetworkChangeActive.value = false
isAllowedDuringAirplaneMode.value = true
}
companion object {

View File

@@ -165,6 +165,13 @@ class CarrierMergedConnectionRepository(
override val isGsm = MutableStateFlow(false).asStateFlow()
override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow()
/**
* Carrier merged connections happen over wifi but are displayed as a mobile triangle. Because
* they occur over wifi, it's possible to have a valid carrier merged connection even during
* airplane mode. See b/291993542.
*/
override val isAllowedDuringAirplaneMode = MutableStateFlow(true).asStateFlow()
override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
companion object {

View File

@@ -287,6 +287,15 @@ class FullMobileConnectionRepository(
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.networkName.value)
override val isAllowedDuringAirplaneMode =
activeRepo
.flatMapLatest { it.isAllowedDuringAirplaneMode }
.stateIn(
scope,
SharingStarted.WhileSubscribed(),
activeRepo.value.isAllowedDuringAirplaneMode.value,
)
class Factory
@Inject
constructor(

View File

@@ -59,8 +59,10 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
@@ -331,6 +333,9 @@ class MobileConnectionRepositoryImpl(
.stateIn(scope, SharingStarted.WhileSubscribed(), initial)
}
/** Typical mobile connections aren't available during airplane mode. */
override val isAllowedDuringAirplaneMode = MutableStateFlow(false).asStateFlow()
class Factory
@Inject
constructor(

View File

@@ -111,6 +111,9 @@ interface MobileIconInteractor {
/** See [MobileIconsInteractor.isForceHidden]. */
val isForceHidden: Flow<Boolean>
/** See [MobileConnectionRepository.isAllowedDuringAirplaneMode]. */
val isAllowedDuringAirplaneMode: StateFlow<Boolean>
/** True when in carrier network change mode */
val carrierNetworkChangeActive: StateFlow<Boolean>
}
@@ -267,4 +270,6 @@ class MobileIconInteractorImpl(
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val isInService = connectionRepository.isInService
override val isAllowedDuringAirplaneMode = connectionRepository.isAllowedDuringAirplaneMode
}

View File

@@ -102,9 +102,16 @@ constructor(
} else {
combine(
airplaneModeInteractor.isAirplaneMode,
iconInteractor.isAllowedDuringAirplaneMode,
iconInteractor.isForceHidden,
) { isAirplaneMode, isForceHidden ->
!isAirplaneMode && !isForceHidden
) { isAirplaneMode, isAllowedDuringAirplaneMode, isForceHidden ->
if (isForceHidden) {
false
} else if (isAirplaneMode) {
isAllowedDuringAirplaneMode
} else {
true
}
}
}
.distinctUntilChanged()

View File

@@ -55,6 +55,8 @@ class FakeMobileConnectionRepository(
override val networkName =
MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
fun setDataEnabled(enabled: Boolean) {
_dataEnabled.value = enabled
}

View File

@@ -20,6 +20,7 @@ import android.telephony.TelephonyManager
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
@@ -319,6 +320,14 @@ class CarrierMergedConnectionRepositoryTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isAllowedDuringAirplaneMode_alwaysTrue() =
testScope.runTest {
val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
assertThat(latest).isTrue()
}
private companion object {
const val SUB_ID = 123
const val NET_ID = 456

View File

@@ -22,6 +22,7 @@ import android.telephony.TelephonyCallback
import android.telephony.TelephonyManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
@@ -84,7 +85,11 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
@Before
fun setUp() {
mobileRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
carrierMergedRepo = FakeMobileConnectionRepository(SUB_ID, tableLogBuffer)
carrierMergedRepo =
FakeMobileConnectionRepository(SUB_ID, tableLogBuffer).apply {
// Mimicks the real carrier merged repository
this.isAllowedDuringAirplaneMode.value = true
}
whenever(
mobileFactory.build(
@@ -299,6 +304,24 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
levelJob.cancel()
}
@Test
fun isAllowedDuringAirplaneMode_updatesWhenCarrierMergedUpdates() =
testScope.runTest {
initializeRepo(startingIsCarrierMerged = false)
val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
assertThat(latest).isFalse()
underTest.setIsCarrierMerged(true)
assertThat(latest).isTrue()
underTest.setIsCarrierMerged(false)
assertThat(latest).isFalse()
}
@Test
fun factory_reusesLogBuffersForSameConnection() =
testScope.runTest {

View File

@@ -53,6 +53,7 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import androidx.test.filters.SmallTest
import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
@@ -812,6 +813,14 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isAllowedDuringAirplaneMode_alwaysFalse() =
testScope.runTest {
val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
assertThat(latest).isFalse()
}
private inline fun <reified T> getTelephonyCallbackForType(): T {
return MobileTelephonyHelpers.getTelephonyCallbackForType(telephonyManager)
}

View File

@@ -77,6 +77,8 @@ class FakeMobileIconInteractor(
override val isForceHidden = MutableStateFlow(false)
override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
fun setIsEmergencyOnly(emergency: Boolean) {
_isEmergencyOnly.value = emergency
}

View File

@@ -23,6 +23,7 @@ import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
@@ -473,6 +474,18 @@ class MobileIconInteractorTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isAllowedDuringAirplaneMode_matchesRepo() =
testScope.runTest {
val latest by collectLastValue(underTest.isAllowedDuringAirplaneMode)
connectionRepository.isAllowedDuringAirplaneMode.value = true
assertThat(latest).isTrue()
connectionRepository.isAllowedDuringAirplaneMode.value = false
assertThat(latest).isFalse()
}
private fun createInteractor(
overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl()
) =

View File

@@ -116,12 +116,13 @@ class MobileIconViewModelTest : SysuiTestCase() {
}
@Test
fun isVisible_airplane_false() =
fun isVisible_airplaneAndNotAllowed_false() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(true)
interactor.isAllowedDuringAirplaneMode.value = false
interactor.isForceHidden.value = false
assertThat(latest).isFalse()
@@ -129,6 +130,22 @@ class MobileIconViewModelTest : SysuiTestCase() {
job.cancel()
}
/** Regression test for b/291993542. */
@Test
fun isVisible_airplaneButAllowed_true() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(true)
interactor.isAllowedDuringAirplaneMode.value = true
interactor.isForceHidden.value = false
assertThat(latest).isTrue()
job.cancel()
}
@Test
fun isVisible_forceHidden_false() =
testScope.runTest {
@@ -157,7 +174,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
airplaneModeRepository.setIsAirplaneMode(true)
assertThat(latest).isFalse()
airplaneModeRepository.setIsAirplaneMode(false)
interactor.isAllowedDuringAirplaneMode.value = true
assertThat(latest).isTrue()
interactor.isForceHidden.value = true