Merge "[Status Bar] Allow carrier merged to be displayed even in airplane mode." into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0a65c06d05
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,8 @@ class FakeMobileIconInteractor(
|
||||
|
||||
override val isForceHidden = MutableStateFlow(false)
|
||||
|
||||
override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
|
||||
|
||||
fun setIsEmergencyOnly(emergency: Boolean) {
|
||||
_isEmergencyOnly.value = emergency
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
) =
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user