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

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

Merge changes I39698d4d,I8c8b67a9 into tm-qpr-dev am: 793e7baf

parents a5d5257d 793e7baf
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -163,8 +163,7 @@ public class StatusBarIconControllerImpl implements Tunable,
        for (int i = currentSlots.size() - 1; i >= 0; i--) {
            Slot s = currentSlots.get(i);
            slotsToReAdd.put(s, s.getHolderList());
            // Don't force here because the new pipeline properly handles the tuner settings
            removeAllIconsForSlot(s.getName(), /* force */ false);
            removeAllIconsForSlot(s.getName(), /* fromNewPipeline */ false);
        }

        // Add them all back
@@ -286,7 +285,7 @@ public class StatusBarIconControllerImpl implements Tunable,
        // Because of the way we cache the icon holders, we need to remove everything any time
        // we get a new set of subscriptions. This might change in the future, but is required
        // to support demo mode for now
        removeAllIconsForSlot(slotName, /* force */ true);
        removeAllIconsForSlot(slotName, /* fromNewPipeline */ true);

        Collections.reverse(subIds);

@@ -453,13 +452,13 @@ public class StatusBarIconControllerImpl implements Tunable,
    /** */
    @Override
    public void removeAllIconsForSlot(String slotName) {
        removeAllIconsForSlot(slotName, /* force */ false);
        removeAllIconsForSlot(slotName, /* fromNewPipeline */ false);
    }

    private void removeAllIconsForSlot(String slotName, Boolean force) {
    private void removeAllIconsForSlot(String slotName, boolean fromNewPipeline) {
        // If the new pipeline is on for this icon, don't allow removal, since the new pipeline
        // will never call this method
        if (!force && mStatusBarPipelineFlags.isIconControlledByFlags(slotName)) {
        if (!fromNewPipeline && mStatusBarPipelineFlags.isIconControlledByFlags(slotName)) {
            Log.i(TAG, "Ignoring removal of (" + slotName + "). "
                    + "It should be controlled elsewhere");
            return;
+8 −2
Original line number Diff line number Diff line
@@ -34,8 +34,14 @@ interface MobileConnectionsRepository {
    /** Observable list of current mobile subscriptions */
    val subscriptions: StateFlow<List<SubscriptionModel>>

    /** Observable for the subscriptionId of the current mobile data connection */
    val activeMobileDataSubscriptionId: StateFlow<Int>
    /**
     * Observable for the subscriptionId of the current mobile data connection. Null if we don't
     * have a valid subscription id
     */
    val activeMobileDataSubscriptionId: StateFlow<Int?>

    /** Repo that tracks the current [activeMobileDataSubscriptionId] */
    val activeMobileDataRepository: StateFlow<MobileConnectionRepository?>

    /**
     * Observable event for when the active data sim switches but the group stays the same. E.g.,
+10 −2
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@ import kotlinx.coroutines.flow.stateIn
 * interface in its own repository, completely separate from the real version, while still using all
 * of the prod implementations for the rest of the pipeline (interactors and onward). Looks
 * something like this:
 *
 * ```
 * RealRepository
 *                 │
@@ -115,7 +114,7 @@ constructor(
            .flatMapLatest { it.subscriptions }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.subscriptions.value)

    override val activeMobileDataSubscriptionId: StateFlow<Int> =
    override val activeMobileDataSubscriptionId: StateFlow<Int?> =
        activeRepo
            .flatMapLatest { it.activeMobileDataSubscriptionId }
            .stateIn(
@@ -124,6 +123,15 @@ constructor(
                realRepository.activeMobileDataSubscriptionId.value
            )

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

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

+10 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
@@ -121,6 +122,15 @@ constructor(
                subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
            )

    override val activeMobileDataRepository: StateFlow<MobileConnectionRepository?> =
        activeMobileDataSubscriptionId
            .map { getRepoForSubId(it) }
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
                getRepoForSubId(activeMobileDataSubscriptionId.value)
            )

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

+47 −21
Original line number Diff line number Diff line
@@ -159,13 +159,16 @@ constructor(
            )
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())

    /** StateFlow that keeps track of the current active mobile data subscription */
    override val activeMobileDataSubscriptionId: StateFlow<Int> =
    override val activeMobileDataSubscriptionId: StateFlow<Int?> =
        conflatedCallbackFlow {
                val callback =
                    object : TelephonyCallback(), ActiveDataSubscriptionIdListener {
                        override fun onActiveDataSubscriptionIdChanged(subId: Int) {
                            if (subId != INVALID_SUBSCRIPTION_ID) {
                                trySend(subId)
                            } else {
                                trySend(null)
                            }
                        }
                    }

@@ -179,7 +182,18 @@ constructor(
                columnName = "activeSubId",
                initialValue = INVALID_SUBSCRIPTION_ID,
            )
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), null)

    override val activeMobileDataRepository =
        activeMobileDataSubscriptionId
            .map { activeSubId ->
                if (activeSubId == null) {
                    null
                } else {
                    getOrCreateRepoForSubId(activeSubId)
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)

    private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
        MutableSharedFlow(extraBufferCapacity = 1)
@@ -240,10 +254,13 @@ constructor(
            )
        }

        return subIdRepositoryCache[subId]
            ?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it }
        return getOrCreateRepoForSubId(subId)
    }

    private fun getOrCreateRepoForSubId(subId: Int) =
        subIdRepositoryCache[subId]
            ?: createRepositoryForSubId(subId).also { subIdRepositoryCache[subId] = it }

    @SuppressLint("MissingPermission")
    override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
        conflatedCallbackFlow {
@@ -292,7 +309,9 @@ constructor(
    override val activeSubChangedInGroupEvent =
        activeMobileDataSubscriptionId
            .pairwise()
            .mapNotNull { (prevVal: Int, newVal: Int) ->
            .mapNotNull { (prevVal: Int?, newVal: Int?) ->
                if (prevVal == null || newVal == null) return@mapNotNull null

                val prevSub = subscriptionManager.getActiveSubscriptionInfo(prevVal)?.groupUuid
                val nextSub = subscriptionManager.getActiveSubscriptionInfo(newVal)?.groupUuid

@@ -300,15 +319,7 @@ constructor(
            }
            .flowOn(bgDispatcher)

    private fun isValidSubId(subId: Int): Boolean {
        subscriptions.value.forEach {
            if (it.subscriptionId == subId) {
                return true
            }
        }

        return false
    }
    private fun isValidSubId(subId: Int): Boolean = checkSub(subId, subscriptions.value)

    @VisibleForTesting fun getSubIdRepoCache() = subIdRepositoryCache

@@ -335,12 +346,27 @@ constructor(
    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 }

        subIdRepositoryCache =
            subIdRepositoryCache
                .filter { currentValidSubscriptionIds.contains(it.key) }
                .toMutableMap()
            subIdRepositoryCache.filter { checkSub(it.key, newInfos) }.toMutableMap()
    }

    /**
     * True if the checked subId is in the list of current subs or the active mobile data subId
     *
     * @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
     * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
     * current known subscriptions
     */
    private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
        if (activeMobileDataSubscriptionId.value == subId) return true

        checkedSubs.forEach {
            if (it.subscriptionId == subId) {
                return true
            }
        }

        return false
    }

    private suspend fun fetchSubscriptionsList(): List<SubscriptionInfo> =
Loading