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

Commit 2b679cec authored by Evan Laird's avatar Evan Laird
Browse files

[Sb refactor] Fix active subId in group event flow

This flow was malformed and would never actually emit based on the
original defintion. Added some tests too to make sure it works

Test: MobileConnectionsRepositoryTest
Bug: 238425913
Change-Id: I7522bf7d34d86632f0b863b73c8f11eaeb620430
parent f7347b49
Loading
Loading
Loading
Loading
+8 −17
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.util.kotlin.pairwiseBy
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -66,10 +66,10 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -287,22 +287,13 @@ constructor(
     */
    @SuppressLint("MissingPermission")
    override val activeSubChangedInGroupEvent =
        flow {
                activeMobileDataSubscriptionId.pairwiseBy { prevVal: Int, newVal: Int ->
                    if (!defaultMobileNetworkConnectivity.value.isValidated) {
                        return@pairwiseBy
                    }
                    val prevSub = subscriptionManager.getActiveSubscriptionInfo(prevVal)
                    val nextSub = subscriptionManager.getActiveSubscriptionInfo(newVal)

                    if (prevSub == null || nextSub == null) {
                        return@pairwiseBy
                    }
        activeMobileDataSubscriptionId
            .pairwise()
            .mapNotNull { (prevVal: Int, newVal: Int) ->
                val prevSub = subscriptionManager.getActiveSubscriptionInfo(prevVal)?.groupUuid
                val nextSub = subscriptionManager.getActiveSubscriptionInfo(newVal)?.groupUuid

                    if (prevSub.groupUuid != null && prevSub.groupUuid == nextSub.groupUuid) {
                        emit(Unit)
                    }
                }
                if (prevSub != null && prevSub == nextSub) Unit else null
            }
            .flowOn(bgDispatcher)

+78 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.os.ParcelUuid
import android.provider.Settings
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionInfo
@@ -50,6 +51,7 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import java.util.UUID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -104,6 +106,17 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
            mock<TableLogBuffer>()
        }

        // For convenience, set up the subscription info callbacks
        whenever(subscriptionManager.getActiveSubscriptionInfo(anyInt())).thenAnswer { invocation ->
            when (invocation.getArgument(0) as Int) {
                1 -> SUB_1
                2 -> SUB_2
                3 -> SUB_3
                4 -> SUB_4
                else -> null
            }
        }

        wifiRepository = FakeWifiRepository()

        connectionFactory =
@@ -686,6 +699,38 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
            job.cancel()
        }

    @Test
    fun `active data change - in same group - emits unit`() =
        runBlocking(IMMEDIATE) {
            var latest: Unit? = null
            val job = underTest.activeSubChangedInGroupEvent.onEach { latest = it }.launchIn(this)

            getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>()
                .onActiveDataSubscriptionIdChanged(SUB_3_ID_GROUPED)
            getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>()
                .onActiveDataSubscriptionIdChanged(SUB_4_ID_GROUPED)

            assertThat(latest).isEqualTo(Unit)

            job.cancel()
        }

    @Test
    fun `active data change - not in same group - does not emit`() =
        runBlocking(IMMEDIATE) {
            var latest: Unit? = null
            val job = underTest.activeSubChangedInGroupEvent.onEach { latest = it }.launchIn(this)

            getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>()
                .onActiveDataSubscriptionIdChanged(SUB_3_ID_GROUPED)
            getTelephonyCallbackForType<ActiveDataSubscriptionIdListener>()
                .onActiveDataSubscriptionIdChanged(SUB_1_ID)

            assertThat(latest).isEqualTo(null)

            job.cancel()
        }

    private fun createCapabilities(connected: Boolean, validated: Boolean): NetworkCapabilities =
        mock<NetworkCapabilities>().also {
            whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(connected)
@@ -719,19 +764,50 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {

    companion object {
        private val IMMEDIATE = Dispatchers.Main.immediate

        // Subscription 1
        private const val SUB_1_ID = 1
        private val SUB_1 =
            mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
            mock<SubscriptionInfo>().also {
                whenever(it.subscriptionId).thenReturn(SUB_1_ID)
                whenever(it.groupUuid).thenReturn(ParcelUuid(UUID.randomUUID()))
            }
        private val MODEL_1 = SubscriptionModel(subscriptionId = SUB_1_ID)

        // Subscription 2
        private const val SUB_2_ID = 2
        private val SUB_2 =
            mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) }
            mock<SubscriptionInfo>().also {
                whenever(it.subscriptionId).thenReturn(SUB_2_ID)
                whenever(it.groupUuid).thenReturn(ParcelUuid(UUID.randomUUID()))
            }
        private val MODEL_2 = SubscriptionModel(subscriptionId = SUB_2_ID)

        // Subs 3 and 4 are considered to be in the same group ------------------------------------
        private val GROUP_ID_3_4 = ParcelUuid(UUID.randomUUID())

        // Subscription 3
        private const val SUB_3_ID_GROUPED = 3
        private val SUB_3 =
            mock<SubscriptionInfo>().also {
                whenever(it.subscriptionId).thenReturn(SUB_3_ID_GROUPED)
                whenever(it.groupUuid).thenReturn(GROUP_ID_3_4)
            }

        // Subscription 4
        private const val SUB_4_ID_GROUPED = 4
        private val SUB_4 =
            mock<SubscriptionInfo>().also {
                whenever(it.subscriptionId).thenReturn(SUB_4_ID_GROUPED)
                whenever(it.groupUuid).thenReturn(GROUP_ID_3_4)
            }

        // Subs 3 and 4 are considered to be in the same group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        private const val NET_ID = 123
        private val NETWORK = mock<Network>().apply { whenever(getNetId()).thenReturn(NET_ID) }

        // Carrier merged subscription
        private const val SUB_CM_ID = 5
        private val SUB_CM =
            mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_CM_ID) }