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

Commit 93791395 authored by Evan Laird's avatar Evan Laird Committed by Automerger Merge Worker
Browse files

Merge changes I1c9ade7e,I06365d19,I0945a29d,I8e798197,Ib3a4f14b, ... into...

Merge changes I1c9ade7e,I06365d19,I0945a29d,I8e798197,Ib3a4f14b, ... into tm-qpr-dev am: 74daba5a am: b9ace6dc

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20932924



Change-Id: I64829531f6f0196bad8342d612ab05fd4253be1b
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents b75b6039 b9ace6dc
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.mobile.data.repository

import android.provider.Settings
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionManager
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.MobileMappings.Config
@@ -37,6 +38,15 @@ interface MobileConnectionsRepository {
    /** Observable for the subscriptionId of the current mobile data connection */
    val activeMobileDataSubscriptionId: StateFlow<Int>

    /**
     * Observable event for when the active data sim switches but the group stays the same. E.g.,
     * CBRS switching would trigger this
     */
    val activeSubChangedInGroupEvent: Flow<Unit>

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

    /** The current connectivity status for the default mobile network connection */
    val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel>

+8 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ constructor(
                realRepository.activeMobileDataSubscriptionId.value
            )

    override val activeSubChangedInGroupEvent: Flow<Unit> =
        activeRepo.flatMapLatest { it.activeSubChangedInGroupEvent }

    override val defaultDataSubRatConfig: StateFlow<MobileMappings.Config> =
        activeRepo
            .flatMapLatest { it.defaultDataSubRatConfig }
@@ -139,6 +142,11 @@ constructor(
    override val defaultMobileIconGroup: Flow<SignalIcon.MobileIconGroup> =
        activeRepo.flatMapLatest { it.defaultMobileIconGroup }

    override val defaultDataSubId: StateFlow<Int> =
        activeRepo
            .flatMapLatest { it.defaultDataSubId }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.defaultDataSubId.value)

    override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
        activeRepo
            .flatMapLatest { it.defaultMobileNetworkConnectivity }
+12 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -120,6 +121,9 @@ constructor(
                subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
            )

    // TODO(b/261029387): consider adding a demo command for this
    override val activeSubChangedInGroupEvent: Flow<Unit> = flowOf()

    /** Demo mode doesn't currently support modifications to the mobile mappings */
    override val defaultDataSubRatConfig =
        MutableStateFlow(MobileMappings.Config.readConfig(context))
@@ -148,8 +152,12 @@ constructor(

    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 = MutableStateFlow(INVALID_SUBSCRIPTION_ID)

    // TODO(b/261029387): not yet supported
    override val defaultMobileNetworkConnectivity = MutableStateFlow(MobileConnectivityModel())
    override val defaultMobileNetworkConnectivity =
        MutableStateFlow(MobileConnectivityModel(isConnected = true, isValidated = true))

    override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
        val current = connectionRepoCache[subId]?.repo
@@ -229,6 +237,9 @@ constructor(
        val connection = getRepoForSubId(subId)
        connectionRepoCache[subId]?.lastMobileState = state

        // TODO(b/261029387): until we have a command, use the most recent subId
        defaultDataSubId.value = subId

        // This is always true here, because we split out disabled states at the data-source level
        connection.dataEnabled.value = true
        connection.networkName.value = NetworkNameModel.Derived(state.name)
+51 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.telephony.TelephonyCallback
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener
import android.telephony.TelephonyManager
import androidx.annotation.VisibleForTesting
import com.android.internal.telephony.PhoneConstants
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.MobileMappings.Config
import com.android.systemui.R
@@ -52,6 +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.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -60,9 +62,12 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
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.merge
@@ -159,10 +164,24 @@ constructor(
            .logInputChange(logger, "onActiveDataSubscriptionIdChanged")
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)

    private val defaultDataSubIdChangedEvent =
    private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
        MutableSharedFlow(extraBufferCapacity = 1)

    override val defaultDataSubId: StateFlow<Int> =
        broadcastDispatcher
            .broadcastFlow(IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED))
            .broadcastFlow(
                IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
            ) { intent, _ ->
                intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
            }
            .distinctUntilChanged()
            .logInputChange(logger, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED")
            .onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                SubscriptionManager.getDefaultDataSubscriptionId()
            )

    private val carrierConfigChangedEvent =
        broadcastDispatcher
@@ -170,7 +189,7 @@ constructor(
            .logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED")

    override val defaultDataSubRatConfig: StateFlow<Config> =
        merge(defaultDataSubIdChangedEvent, carrierConfigChangedEvent)
        merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
            .mapLatest { Config.readConfig(context) }
            .distinctUntilChanged()
            .logInputChange(logger, "defaultDataSubRatConfig")
@@ -258,6 +277,35 @@ constructor(
            .logInputChange(logger, "defaultMobileNetworkConnectivity")
            .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())

    /**
     * Flow that tracks the active mobile data subscriptions. Emits `true` whenever the active data
     * subscription Id changes but the subscription group remains the same. In these cases, we want
     * to retain the previous subscription's validation status for up to 2s to avoid flickering the
     * icon.
     *
     * TODO(b/265164432): we should probably expose all change events, not just same group
     */
    @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
                    }

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

    private fun isValidSubId(subId: Int): Boolean {
        subscriptions.value.forEach {
            if (it.subscriptionId == subId) {
+41 −4
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor

import android.telephony.CarrierConfigManager
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.TelephonyIcons.NOT_DEFAULT_DATA
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
@@ -41,12 +43,29 @@ interface MobileIconInteractor {
    /** The current mobile data activity */
    val activity: Flow<DataActivityModel>

    /** Only true if mobile is the default transport but is not validated, otherwise false */
    val isDefaultConnectionFailed: StateFlow<Boolean>
    /**
     * This bit is meant to be `true` if and only if the default network capabilities (see
     * [android.net.ConnectivityManager.registerDefaultNetworkCallback]) result in a network that
     * has the [android.net.NetworkCapabilities.TRANSPORT_CELLULAR] represented.
     *
     * Note that this differs from [isDataConnected], which is tracked by telephony and has to do
     * with the state of using this mobile connection for data as opposed to just voice. It is
     * possible for a mobile subscription to be connected but not be in a connected data state, and
     * thus we wouldn't want to show the network type icon.
     */
    val isConnected: Flow<Boolean>

    /** True when telephony tells us that the data state is CONNECTED */
    /**
     * True when telephony tells us that the data state is CONNECTED. See
     * [android.telephony.TelephonyCallback.DataConnectionStateListener] for more details. We
     * consider this connection to be serving data, and thus want to show a network type icon, when
     * data is connected. Other data connection states would typically cause us not to show the icon
     */
    val isDataConnected: StateFlow<Boolean>

    /** Only true if mobile is the default transport but is not validated, otherwise false */
    val isDefaultConnectionFailed: StateFlow<Boolean>

    /** True if we consider this connection to be in service, i.e. can make calls */
    val isInService: StateFlow<Boolean>

@@ -100,8 +119,10 @@ class MobileIconInteractorImpl(
    defaultSubscriptionHasDataEnabled: StateFlow<Boolean>,
    override val alwaysShowDataRatIcon: StateFlow<Boolean>,
    override val alwaysUseCdmaLevel: StateFlow<Boolean>,
    defaultMobileConnectivity: StateFlow<MobileConnectivityModel>,
    defaultMobileIconMapping: StateFlow<Map<String, MobileIconGroup>>,
    defaultMobileIconGroup: StateFlow<MobileIconGroup>,
    defaultDataSubId: StateFlow<Int>,
    override val isDefaultConnectionFailed: StateFlow<Boolean>,
    connectionRepository: MobileConnectionRepository,
) : MobileIconInteractor {
@@ -111,8 +132,19 @@ class MobileIconInteractorImpl(

    override val activity = connectionInfo.mapLatest { it.dataActivityDirection }

    override val isConnected: Flow<Boolean> = defaultMobileConnectivity.mapLatest { it.isConnected }

    override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled

    private val isDefault =
        defaultDataSubId
            .mapLatest { connectionRepository.subId == it }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                connectionRepository.subId == defaultDataSubId.value
            )

    override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled

    override val networkName =
@@ -137,7 +169,12 @@ class MobileIconInteractorImpl(
                connectionInfo,
                defaultMobileIconMapping,
                defaultMobileIconGroup,
            ) { info, mapping, defaultGroup ->
                isDefault,
            ) { info, mapping, defaultGroup, isDefault ->
                if (!isDefault) {
                    return@combine NOT_DEFAULT_DATA
                }

                when (info.resolvedNetworkType) {
                    is ResolvedNetworkType.CarrierMergedNetworkType ->
                        info.resolvedNetworkType.iconGroupOverride
Loading