Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit daeb168c authored by Evan Laird's avatar Evan Laird
Browse files

[sat] use new ntn signal strength TelephonyCallback

This can replace the current method of calculating the signal strength
for a carrier NTN connection.

Test: MobileIconInteractorTest
Bug: 377518113
Flag: com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn
Change-Id: Id64d90a8e55de3ac5f0c72d78ccfe2664c83a93a
parent 3f6296a7
Loading
Loading
Loading
Loading
+71 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar.pipeline.mobile.domain.interactor

import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.telephony.CellSignalStrength
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
@@ -735,9 +736,10 @@ class MobileIconInteractorTest : SysuiTestCase() {
        }

    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
    @DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    @Test
    // See b/346904529 for more context
    fun satBasedIcon_doesNotInflateSignalStrength() =
    fun satBasedIcon_doesNotInflateSignalStrength_flagOff() =
        testScope.runTest {
            val latest by collectLastValue(underTest.signalLevelIcon)

@@ -756,7 +758,75 @@ class MobileIconInteractorTest : SysuiTestCase() {
            assertThat(latest!!.level).isEqualTo(4)
        }

    @EnableFlags(
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
    )
    @Test
    // See b/346904529 for more context
    fun satBasedIcon_doesNotInflateSignalStrength_flagOn() =
        testScope.runTest {
            val latest by collectLastValue(underTest.signalLevelIcon)

            // GIVEN a satellite connection
            connectionRepository.isNonTerrestrial.value = true
            // GIVEN this carrier has set INFLATE_SIGNAL_STRENGTH
            connectionRepository.inflateSignalStrength.value = true

            connectionRepository.satelliteLevel.value = 4
            assertThat(latest!!.level).isEqualTo(4)

            connectionRepository.inflateSignalStrength.value = true
            connectionRepository.primaryLevel.value = 4

            // Icon level is unaffected
            assertThat(latest!!.level).isEqualTo(4)
        }

    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
    @DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    @Test
    fun satBasedIcon_usesPrimaryLevel_flagOff() =
        testScope.runTest {
            val latest by collectLastValue(underTest.signalLevelIcon)

            // GIVEN a satellite connection
            connectionRepository.isNonTerrestrial.value = true

            // GIVEN primary level is set
            connectionRepository.primaryLevel.value = 4
            connectionRepository.satelliteLevel.value = 0

            // THEN icon uses the primary level because the flag is off
            assertThat(latest!!.level).isEqualTo(4)
        }

    @EnableFlags(
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
    )
    @Test
    fun satBasedIcon_usesSatelliteLevel_flagOn() =
        testScope.runTest {
            val latest by collectLastValue(underTest.signalLevelIcon)

            // GIVEN a satellite connection
            connectionRepository.isNonTerrestrial.value = true

            // GIVEN satellite level is set
            connectionRepository.satelliteLevel.value = 4
            connectionRepository.primaryLevel.value = 0

            // THEN icon uses the satellite level because the flag is on
            assertThat(latest!!.level).isEqualTo(4)
        }

    /**
     * Context (b/377518113), this test will not be needed after FLAG_CARRIER_ROAMING_NB_IOT_NTN is
     * rolled out. The new API should report 0 automatically if not in service.
     */
    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
    @DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    @Test
    fun satBasedIcon_reportsLevelZeroWhenOutOfService() =
        testScope.runTest {
+99 −44
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
                iconsInteractor.isForceHidden,
                repository,
                context,
                MobileIconCarrierIdOverridesFake()
                MobileIconCarrierIdOverridesFake(),
            )
        createAndSetViewModel()
    }
@@ -359,7 +359,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            connectionsRepository.mobileIsDefault.value = true
            repository.setNetworkTypeKey(connectionsRepository.GSM_KEY)
@@ -406,7 +406,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            repository.setNetworkTypeKey(connectionsRepository.GSM_KEY)
            repository.setDataEnabled(true)
@@ -426,7 +426,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val initial =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )

            repository.setNetworkTypeKey(connectionsRepository.GSM_KEY)
@@ -448,7 +448,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            repository.dataEnabled.value = true
            var latest: Icon? = null
@@ -477,7 +477,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            assertThat(latest).isEqualTo(expected)

@@ -499,7 +499,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            assertThat(latest).isEqualTo(expected)

@@ -520,7 +520,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            assertThat(latest).isEqualTo(expected)

@@ -542,7 +542,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    connectionsRepository.defaultMobileIconGroup.value.dataType,
                    ContentDescription.Resource(G.dataContentDescription)
                    ContentDescription.Resource(G.dataContentDescription),
                )

            assertThat(latest).isEqualTo(expected)
@@ -564,7 +564,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            val expected =
                Icon.Resource(
                    THREE_G.dataType,
                    ContentDescription.Resource(THREE_G.dataContentDescription)
                    ContentDescription.Resource(THREE_G.dataContentDescription),
                )
            assertThat(latest).isEqualTo(expected)

@@ -621,10 +621,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
                underTest.activityInVisible.onEach { containerVisible = it }.launchIn(this)

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = true,
                    hasActivityOut = true,
                )
                DataActivityModel(hasActivityIn = true, hasActivityOut = true)

            assertThat(inVisible).isFalse()
            assertThat(outVisible).isFalse()
@@ -654,10 +651,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
                underTest.activityContainerVisible.onEach { containerVisible = it }.launchIn(this)

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = true,
                    hasActivityOut = false,
                )
                DataActivityModel(hasActivityIn = true, hasActivityOut = false)

            yield()

@@ -666,20 +660,14 @@ class MobileIconViewModelTest : SysuiTestCase() {
            assertThat(containerVisible).isTrue()

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = false,
                    hasActivityOut = true,
                )
                DataActivityModel(hasActivityIn = false, hasActivityOut = true)

            assertThat(inVisible).isFalse()
            assertThat(outVisible).isTrue()
            assertThat(containerVisible).isTrue()

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = false,
                    hasActivityOut = false,
                )
                DataActivityModel(hasActivityIn = false, hasActivityOut = false)

            assertThat(inVisible).isFalse()
            assertThat(outVisible).isFalse()
@@ -709,10 +697,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
                underTest.activityContainerVisible.onEach { containerVisible = it }.launchIn(this)

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = true,
                    hasActivityOut = false,
                )
                DataActivityModel(hasActivityIn = true, hasActivityOut = false)

            yield()

@@ -721,20 +706,14 @@ class MobileIconViewModelTest : SysuiTestCase() {
            assertThat(containerVisible).isTrue()

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = false,
                    hasActivityOut = true,
                )
                DataActivityModel(hasActivityIn = false, hasActivityOut = true)

            assertThat(inVisible).isFalse()
            assertThat(outVisible).isTrue()
            assertThat(containerVisible).isTrue()

            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = false,
                    hasActivityOut = false,
                )
                DataActivityModel(hasActivityIn = false, hasActivityOut = false)

            assertThat(inVisible).isFalse()
            assertThat(outVisible).isFalse()
@@ -824,10 +803,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
            // sets the background on cellular
            repository.hasPrioritizedNetworkCapabilities.value = true
            repository.dataActivityDirection.value =
                DataActivityModel(
                    hasActivityIn = true,
                    hasActivityOut = true,
                )
                DataActivityModel(hasActivityIn = true, hasActivityOut = true)

            assertThat(roaming).isFalse()
            assertThat(networkTypeIcon).isNull()
@@ -838,11 +814,13 @@ class MobileIconViewModelTest : SysuiTestCase() {
        }

    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
    @DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    @Test
    fun nonTerrestrial_usesSatelliteIcon() =
    fun nonTerrestrial_usesSatelliteIcon_flagOff() =
        testScope.runTest {
            repository.isNonTerrestrial.value = true
            repository.setAllLevels(0)
            repository.satelliteLevel.value = 0

            val latest by
                collectLastValue(underTest.icon.filterIsInstance(SignalIconModel.Satellite::class))
@@ -853,28 +831,66 @@ class MobileIconViewModelTest : SysuiTestCase() {

            // 1-2 -> 1 bar
            repository.setAllLevels(1)
            repository.satelliteLevel.value = 1
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            repository.setAllLevels(2)
            repository.satelliteLevel.value = 2
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            // 3-4 -> 2 bars
            repository.setAllLevels(3)
            repository.satelliteLevel.value = 3
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)

            repository.setAllLevels(4)
            repository.satelliteLevel.value = 4
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
        }

    @EnableFlags(
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
    )
    @Test
    fun nonTerrestrial_usesSatelliteIcon_flagOn() =
        testScope.runTest {
            repository.isNonTerrestrial.value = true
            repository.satelliteLevel.value = 0

            val latest by
                collectLastValue(underTest.icon.filterIsInstance(SignalIconModel.Satellite::class))

            // Level 0 -> no connection
            assertThat(latest).isNotNull()
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_0)

            // 1-2 -> 1 bar
            repository.satelliteLevel.value = 1
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            repository.satelliteLevel.value = 2
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            // 3-4 -> 2 bars
            repository.satelliteLevel.value = 3
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)

            repository.satelliteLevel.value = 4
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
        }

    @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
    @DisableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
    @Test
    fun satelliteIcon_ignoresInflateSignalStrength() =
    fun satelliteIcon_ignoresInflateSignalStrength_flagOff() =
        testScope.runTest {
            // Note that this is the exact same test as above, but with inflateSignalStrength set to
            // true we note that the level is unaffected by inflation
            repository.inflateSignalStrength.value = true
            repository.isNonTerrestrial.value = true
            repository.setAllLevels(0)
            repository.satelliteLevel.value = 0

            val latest by
                collectLastValue(underTest.icon.filterIsInstance(SignalIconModel.Satellite::class))
@@ -885,16 +901,55 @@ class MobileIconViewModelTest : SysuiTestCase() {

            // 1-2 -> 1 bar
            repository.setAllLevels(1)
            repository.satelliteLevel.value = 1
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            repository.setAllLevels(2)
            repository.satelliteLevel.value = 2
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            // 3-4 -> 2 bars
            repository.setAllLevels(3)
            repository.satelliteLevel.value = 3
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)

            repository.setAllLevels(4)
            repository.satelliteLevel.value = 4
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
        }

    @EnableFlags(
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG,
        com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN,
    )
    @Test
    fun satelliteIcon_ignoresInflateSignalStrength_flagOn() =
        testScope.runTest {
            // Note that this is the exact same test as above, but with inflateSignalStrength set to
            // true we note that the level is unaffected by inflation
            repository.inflateSignalStrength.value = true
            repository.isNonTerrestrial.value = true
            repository.satelliteLevel.value = 0

            val latest by
                collectLastValue(underTest.icon.filterIsInstance(SignalIconModel.Satellite::class))

            // Level 0 -> no connection
            assertThat(latest).isNotNull()
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_0)

            // 1-2 -> 1 bar
            repository.satelliteLevel.value = 1
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            repository.satelliteLevel.value = 2
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_1)

            // 3-4 -> 2 bars
            repository.satelliteLevel.value = 3
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)

            repository.satelliteLevel.value = 4
            assertThat(latest!!.icon.res).isEqualTo(R.drawable.ic_satellite_connected_2)
        }

+20 −19
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.telephony.ServiceState
import android.telephony.SignalStrength
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
import android.telephony.satellite.NtnSignalStrength
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.dagger.SysUISingleton
@@ -31,11 +32,7 @@ import javax.inject.Inject

/** Logs for inputs into the mobile pipeline. */
@SysUISingleton
class MobileInputLogger
@Inject
constructor(
    @MobileInputLog private val buffer: LogBuffer,
) {
class MobileInputLogger @Inject constructor(@MobileInputLog private val buffer: LogBuffer) {
    fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
        buffer.log(
            TAG,
@@ -49,7 +46,7 @@ constructor(
            {
                "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
                    " operator=$str1"
            }
            },
        )
    }

@@ -61,7 +58,7 @@ constructor(
                int1 = subId
                bool1 = serviceState.isEmergencyOnly
            },
            { "ACTION_SERVICE_STATE for subId=$int1. ServiceState.isEmergencyOnly=$bool1" }
            { "ACTION_SERVICE_STATE for subId=$int1. ServiceState.isEmergencyOnly=$bool1" },
        )
    }

@@ -70,7 +67,7 @@ constructor(
            TAG,
            LogLevel.INFO,
            { int1 = subId },
            { "ACTION_SERVICE_STATE for subId=$int1. Intent is missing extras. Ignoring" }
            { "ACTION_SERVICE_STATE for subId=$int1. Intent is missing extras. Ignoring" },
        )
    }

@@ -82,7 +79,16 @@ constructor(
                int1 = subId
                str1 = signalStrength.toString()
            },
            { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" }
            { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" },
        )
    }

    fun logNtnSignalStrengthChanged(signalStrength: NtnSignalStrength) {
        buffer.log(
            TAG,
            LogLevel.INFO,
            { int1 = signalStrength.level },
            { "onCarrierRoamingNtnSignalStrengthChanged: level=$int1" },
        )
    }

@@ -128,7 +134,7 @@ constructor(
            TAG,
            LogLevel.INFO,
            { bool1 = active },
            { "onCarrierRoamingNtnModeChanged: $bool1" }
            { "onCarrierRoamingNtnModeChanged: $bool1" },
        )
    }

@@ -146,12 +152,7 @@ constructor(
    }

    fun logCarrierConfigChanged(subId: Int) {
        buffer.log(
            TAG,
            LogLevel.INFO,
            { int1 = subId },
            { "onCarrierConfigChanged: subId=$int1" },
        )
        buffer.log(TAG, LogLevel.INFO, { int1 = subId }, { "onCarrierConfigChanged: subId=$int1" })
    }

    fun logOnDataEnabledChanged(enabled: Boolean, subId: Int) {
@@ -175,7 +176,7 @@ constructor(
            TAG,
            LogLevel.INFO,
            { str1 = config.toString() },
            { "defaultDataSubRatConfig: $str1" }
            { "defaultDataSubRatConfig: $str1" },
        )
    }

@@ -184,7 +185,7 @@ constructor(
            TAG,
            LogLevel.INFO,
            { str1 = mapping.toString() },
            { "defaultMobileIconMapping: $str1" }
            { "defaultMobileIconMapping: $str1" },
        )
    }

@@ -216,7 +217,7 @@ constructor(
            {
                "Intent: ACTION_SERVICE_PROVIDERS_UPDATED." +
                    " showSpn=$bool1 spn=$str1 dataSpn=$str2 showPlmn=$bool2 plmn=$str3"
            }
            },
        )
    }

+6 −0
Original line number Diff line number Diff line
@@ -107,6 +107,12 @@ interface MobileConnectionRepository {
    // @IntRange(from = 0, to = 4)
    val primaryLevel: StateFlow<Int>

    /**
     * This level can be used to reflect the signal strength when in carrier roaming NTN mode
     * (carrier-based satellite)
     */
    val satelliteLevel: StateFlow<Int>

    /** The current data connection state. See [DataConnectionState] */
    val dataConnectionState: StateFlow<DataConnectionState>

+24 −16

File changed.

Preview size limit exceeded, changes collapsed.

Loading