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

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

Add a SubscriptionModel

We currently only need 2 bits from `SubscriptionInfo`: subscriptionId
and isOpportunistic. This CL moves those into a `SubscriptionModel`
class and updates all of the usages.

Test: existing tests
Bug: 249790009
Change-Id: I87686213e68b199b7d4c998f02d6687dcb276a27
parent 9014672c
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.pipeline.mobile.data.model

/**
 * SystemUI representation of [SubscriptionInfo]. Currently we only use two fields on the
 * subscriptions themselves: subscriptionId and isOpportunistic. Any new fields that we need can be
 * added below and provided in the repository classes
 */
data class SubscriptionModel(
    val subscriptionId: Int,
    /**
     * True if the subscription that this model represents has [SubscriptionInfo.isOpportunistic].
     * Opportunistic networks are networks with limited coverage, and we use this bit to determine
     * filtering in certain cases. See [MobileIconsInteractor] for the filtering logic
     */
    val isOpportunistic: Boolean = false,
)
+2 −2
Original line number Diff line number Diff line
@@ -17,10 +17,10 @@
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.SignalIcon.MobileIconGroup
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

@@ -30,7 +30,7 @@ import kotlinx.coroutines.flow.StateFlow
 */
interface MobileConnectionsRepository {
    /** Observable list of current mobile subscriptions */
    val subscriptionsFlow: StateFlow<List<SubscriptionInfo>>
    val subscriptions: StateFlow<List<SubscriptionModel>>

    /** Observable for the subscriptionId of the current mobile data connection */
    val activeMobileDataSubscriptionId: StateFlow<Int>
+4 −8
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
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.SignalIcon
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -25,6 +24,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
import javax.inject.Inject
@@ -109,14 +109,10 @@ constructor(
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realRepository)

    override val subscriptionsFlow: StateFlow<List<SubscriptionInfo>> =
    override val subscriptions: StateFlow<List<SubscriptionModel>> =
        activeRepo
            .flatMapLatest { it.subscriptionsFlow }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                realRepository.subscriptionsFlow.value
            )
            .flatMapLatest { it.subscriptions }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.subscriptions.value)

    override val activeMobileDataSubscriptionId: StateFlow<Int> =
        activeRepo
+10 −30
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo

import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.util.Log
import com.android.settingslib.SignalIcon
@@ -29,6 +28,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectio
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
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.model.SubscriptionModel
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
@@ -62,16 +62,16 @@ constructor(
    private var demoCommandJob: Job? = null

    private val connectionRepoCache = mutableMapOf<Int, DemoMobileConnectionRepository>()
    private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionInfo>()
    private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionModel>()
    val demoModeFinishedEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)

    private val _subscriptions = MutableStateFlow<List<SubscriptionInfo>>(listOf())
    override val subscriptionsFlow =
    private val _subscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
    override val subscriptions =
        _subscriptions
            .onEach { infos -> dropUnusedReposFromCache(infos) }
            .stateIn(scope, SharingStarted.WhileSubscribed(), _subscriptions.value)

    private fun dropUnusedReposFromCache(newInfos: List<SubscriptionInfo>) {
    private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
        // Remove any connection repository from the cache that isn't in the new set of IDs. They
        // will get garbage collected once their subscribers go away
        val currentValidSubscriptionIds = newInfos.map { it.subscriptionId }
@@ -85,37 +85,17 @@ constructor(

    private fun maybeCreateSubscription(subId: Int) {
        if (!subscriptionInfoCache.containsKey(subId)) {
            createSubscriptionForSubId(subId, subId).also { subscriptionInfoCache[subId] = it }
            SubscriptionModel(subscriptionId = subId, isOpportunistic = false).also {
                subscriptionInfoCache[subId] = it
            }

            _subscriptions.value = subscriptionInfoCache.values.toList()
        }
    }

    /** Mimics the old NetworkControllerImpl for now */
    private fun createSubscriptionForSubId(subId: Int, slotIndex: Int): SubscriptionInfo {
        return SubscriptionInfo(
            subId,
            "",
            slotIndex,
            "",
            "",
            0,
            0,
            "",
            0,
            null,
            null,
            null,
            "",
            false,
            null,
            null,
        )
    }

    // TODO(b/261029387): add a command for this value
    override val activeMobileDataSubscriptionId =
        subscriptionsFlow
        subscriptions
            .mapLatest { infos ->
                // For now, active is just the first in the list
                infos.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
@@ -123,7 +103,7 @@ constructor(
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                subscriptionsFlow.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
                subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
            )

    /** Demo mode doesn't currently support modifications to the mobile mappings */
+11 −4
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
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.util.MobileMappingsProxy
@@ -93,7 +94,7 @@ constructor(
     * [SubscriptionInfo]. We probably only need the [SubscriptionInfo.getSubscriptionId] of each
     * info object, but for now we keep track of the infos themselves.
     */
    override val subscriptionsFlow: StateFlow<List<SubscriptionInfo>> =
    override val subscriptions: StateFlow<List<SubscriptionModel>> =
        conflatedCallbackFlow {
                val callback =
                    object : SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -109,7 +110,7 @@ constructor(

                awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
            }
            .mapLatest { fetchSubscriptionsList() }
            .mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
            .onEach { infos -> dropUnusedReposFromCache(infos) }
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())

@@ -239,7 +240,7 @@ constructor(
            .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())

    private fun isValidSubId(subId: Int): Boolean {
        subscriptionsFlow.value.forEach {
        subscriptions.value.forEach {
            if (it.subscriptionId == subId) {
                return true
            }
@@ -258,7 +259,7 @@ constructor(
        )
    }

    private fun dropUnusedReposFromCache(newInfos: List<SubscriptionInfo>) {
    private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
        // Remove any connection repository from the cache that isn't in the new set of IDs. They
        // will get garbage collected once their subscribers go away
        val currentValidSubscriptionIds = newInfos.map { it.subscriptionId }
@@ -272,4 +273,10 @@ constructor(

    private suspend fun fetchSubscriptionsList(): List<SubscriptionInfo> =
        withContext(bgDispatcher) { subscriptionManager.completeActiveSubscriptionInfoList }

    private fun SubscriptionInfo.toSubscriptionModel(): SubscriptionModel =
        SubscriptionModel(
            subscriptionId = subscriptionId,
            isOpportunistic = isOpportunistic,
        )
}
Loading