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

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

Better mapping lookup for demo mode

Move the entire lookup into `MobileMappings` to the
repository layer. So when network types come down, they are immediately
transformed into `ResolvedNetworkType` objects and given a key at that
moment, using the default mobile mapping config

This allows us to A) better insulate us from external depenencies and B)
implement a very trivial mapping for Demo mode. TBD on whether or not we
should allow switching to use the real mobile mappings implementation

Test: tests in tests/src/com/andrdoid/systemui/statusbar/pipeline/mobile/*
Bug: 261185097
Change-Id: I727ad3ca823f3eb225a56f371aa3cef46c340f57
parent cc43d6a8
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.telephony.TelephonyCallback.ServiceStateListener
import android.telephony.TelephonyCallback.SignalStrengthsListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected

/**
@@ -65,5 +64,5 @@ data class MobileSubscriptionModel(
     * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
     * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
     */
    val resolvedNetworkType: ResolvedNetworkType = DefaultNetworkType(NETWORK_TYPE_UNKNOWN),
    val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
)
+16 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.pipeline.mobile.data.model

import android.telephony.Annotation.NetworkType
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy

/**
@@ -26,8 +27,20 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 */
sealed interface ResolvedNetworkType {
    @NetworkType val type: Int
    val lookupKey: String

    object UnknownNetworkType : ResolvedNetworkType {
        override val type: Int = NETWORK_TYPE_UNKNOWN
        override val lookupKey: String = "unknown"
    }

data class DefaultNetworkType(@NetworkType override val type: Int) : ResolvedNetworkType
    data class DefaultNetworkType(
        @NetworkType override val type: Int,
        override val lookupKey: String,
    ) : ResolvedNetworkType

data class OverrideNetworkType(@NetworkType override val type: Int) : ResolvedNetworkType
    data class OverrideNetworkType(
        @NetworkType override val type: Int,
        override val lookupKey: String,
    ) : ResolvedNetworkType
}
+7 −5
Original line number Diff line number Diff line
@@ -19,8 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository
import android.provider.Settings
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.MobileMappings.Config
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
@@ -36,9 +35,6 @@ interface MobileConnectionsRepository {
    /** Observable for the subscriptionId of the current mobile data connection */
    val activeMobileDataSubscriptionId: StateFlow<Int>

    /** Observable for [MobileMappings.Config] tracking the defaults */
    val defaultDataSubRatConfig: StateFlow<Config>

    /** Tracks [SubscriptionManager.getDefaultDataSubscriptionId] */
    val defaultDataSubId: StateFlow<Int>

@@ -50,4 +46,10 @@ interface MobileConnectionsRepository {

    /** Observe changes to the [Settings.Global.MOBILE_DATA] setting */
    val globalMobileDataSettingChangedEvent: Flow<Unit>

    /** The icon mapping from network type to [MobileIconGroup] for the default subscription */
    val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>>

    /** Fallback [MobileIconGroup] in the case where there is no icon in the mapping */
    val defaultMobileIconGroup: Flow<MobileIconGroup>
}
+6 −9
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository
import android.os.Bundle
import android.telephony.SubscriptionInfo
import androidx.annotation.VisibleForTesting
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.SignalIcon
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.demomode.DemoMode
@@ -127,14 +127,11 @@ constructor(
                realRepository.activeMobileDataSubscriptionId.value
            )

    override val defaultDataSubRatConfig: StateFlow<MobileMappings.Config> =
        activeRepo
            .flatMapLatest { it.defaultDataSubRatConfig }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                realRepository.defaultDataSubRatConfig.value
            )
    override val defaultMobileIconMapping: Flow<Map<String, SignalIcon.MobileIconGroup>> =
        activeRepo.flatMapLatest { it.defaultMobileIconMapping }

    override val defaultMobileIconGroup: Flow<SignalIcon.MobileIconGroup> =
        activeRepo.flatMapLatest { it.defaultMobileIconGroup }

    override val defaultDataSubId: StateFlow<Int> =
        activeRepo
+49 −43
Original line number Diff line number Diff line
@@ -17,26 +17,18 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo

import android.content.Context
import android.telephony.Annotation
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED
import android.telephony.TelephonyManager.NETWORK_TYPE_GSM
import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
import android.telephony.TelephonyManager.NETWORK_TYPE_NR
import android.telephony.TelephonyManager.NETWORK_TYPE_UMTS
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import android.util.Log
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
@@ -49,7 +41,9 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -133,8 +127,31 @@ constructor(
            )

    /** Demo mode doesn't currently support modifications to the mobile mappings */
    override val defaultDataSubRatConfig =
        MutableStateFlow(MobileMappings.Config.readConfig(context))
    val defaultDataSubRatConfig = MutableStateFlow(MobileMappings.Config.readConfig(context))

    override val defaultMobileIconGroup = flowOf(TelephonyIcons.THREE_G)

    override val defaultMobileIconMapping = MutableStateFlow(TelephonyIcons.ICON_NAME_TO_ICON)

    /**
     * In order to maintain compatibility with the old demo mode shell command API, reverse the
     * [MobileMappings] lookup from (NetworkType: String -> Icon: MobileIconGroup), so that we can
     * parse the string from the command line into a preferred icon group, and send _a_ valid
     * network type for that icon through the pipeline.
     *
     * Note: collisions don't matter here, because the data source (the command line) only cares
     * about the resulting icon, not the underlying network type.
     */
    private val mobileMappingsReverseLookup: StateFlow<Map<SignalIcon.MobileIconGroup, String>> =
        defaultMobileIconMapping
            .mapLatest { networkToIconMap -> networkToIconMap.reverse() }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                defaultMobileIconMapping.value.reverse()
            )

    private fun <K, V> Map<K, V>.reverse() = entries.associateBy({ it.value }) { it.key }

    // TODO(b/261029387): add a command for this value
    override val defaultDataSubId =
@@ -229,43 +246,32 @@ constructor(
    private fun subIdsString(): String =
        _subscriptions.value.joinToString(",") { it.subscriptionId.toString() }

    companion object {
        private const val TAG = "DemoMobileConnectionsRepo"

        private const val DEFAULT_SUB_ID = 1
    }
}

    private fun Mobile.toMobileSubscriptionModel(): MobileSubscriptionModel {
        return MobileSubscriptionModel(
            isEmergencyOnly = false, // TODO(b/261029387): not yet supported
            isGsm = false, // TODO(b/261029387): not yet supported
            cdmaLevel = level ?: 0,
            primaryLevel = level ?: 0,
        dataConnectionState = DataConnectionState.Connected, // TODO(b/261029387): not yet supported
            dataConnectionState =
                DataConnectionState.Connected, // TODO(b/261029387): not yet supported
            dataActivityDirection = activity,
            carrierNetworkChangeActive = carrierNetworkChange,
        // TODO(b/261185097): once mobile mappings can be mocked at this layer, we can build our
        //  own demo map
            resolvedNetworkType = dataType.toResolvedNetworkType()
        )
    }

@Annotation.NetworkType
private fun SignalIcon.MobileIconGroup?.toNetworkType(): Int =
    when (this) {
        TelephonyIcons.THREE_G -> NETWORK_TYPE_GSM
        TelephonyIcons.LTE -> NETWORK_TYPE_LTE
        TelephonyIcons.FOUR_G -> NETWORK_TYPE_UMTS
        TelephonyIcons.NR_5G -> NETWORK_TYPE_NR
        TelephonyIcons.NR_5G_PLUS -> OVERRIDE_NETWORK_TYPE_NR_ADVANCED
        else -> NETWORK_TYPE_UNKNOWN
    private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
        val key = mobileMappingsReverseLookup.value[this] ?: "dis"
        return DefaultNetworkType(DEMO_NET_TYPE, key)
    }

private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType =
    when (this) {
        TelephonyIcons.NR_5G_PLUS -> OverrideNetworkType(toNetworkType())
        else -> DefaultNetworkType(toNetworkType())
    companion object {
        private const val TAG = "DemoMobileConnectionsRepo"

        private const val DEFAULT_SUB_ID = 1

        private const val DEMO_NET_TYPE = 1234
    }
}

class DemoMobileConnectionRepository(override val subId: Int) : MobileConnectionRepository {
Loading