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

Commit 49f1e9e0 authored by Evan Laird's avatar Evan Laird
Browse files

[Sb refactor] Move DemoMobileConnectionRepository to its own file

This class has outgrown being a small data class defined in the same
file as its parent repo.

Test: DemoMobileConnectionsRepositoryTest; DemoMobileConnectionParameterizedTest
Bug: 270300839
Change-Id: I4981e641c0d4c8346ec46a5a832044df62051a8f
parent 5cbcba28
Loading
Loading
Loading
Loading
+231 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.repository.demo

import android.telephony.CellSignalStrength
import android.telephony.TelephonyManager
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
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
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CARRIER_NETWORK_CHANGE
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_CDMA_LEVEL
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.stateIn

/**
 * Demo version of [MobileConnectionRepository]. Note that this class shares all of its flows using
 * [SharingStarted.WhileSubscribed()] to give the same semantics as using a regular
 * [MutableStateFlow] while still logging all of the inputs in the same manor as the production
 * repos.
 */
class DemoMobileConnectionRepository(
    override val subId: Int,
    override val tableLogBuffer: TableLogBuffer,
    val scope: CoroutineScope,
) : MobileConnectionRepository {
    private val _isEmergencyOnly = MutableStateFlow(false)
    override val isEmergencyOnly =
        _isEmergencyOnly
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_EMERGENCY,
                _isEmergencyOnly.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)

    private val _isRoaming = MutableStateFlow(false)
    override val isRoaming =
        _isRoaming
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_ROAMING,
                _isRoaming.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)

    private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
    override val operatorAlphaShort =
        _operatorAlphaShort
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_OPERATOR,
                _operatorAlphaShort.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)

    private val _isInService = MutableStateFlow(false)
    override val isInService =
        _isInService
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_IS_IN_SERVICE,
                _isInService.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)

    private val _isGsm = MutableStateFlow(false)
    override val isGsm =
        _isGsm
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_IS_GSM,
                _isGsm.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)

    private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
    override val cdmaLevel =
        _cdmaLevel
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_CDMA_LEVEL,
                _cdmaLevel.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)

    private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
    override val primaryLevel =
        _primaryLevel
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_PRIMARY_LEVEL,
                _primaryLevel.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)

    private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
    override val dataConnectionState =
        _dataConnectionState
            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value)
            .stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value)

    private val _dataActivityDirection =
        MutableStateFlow(
            DataActivityModel(
                hasActivityIn = false,
                hasActivityOut = false,
            )
        )
    override val dataActivityDirection =
        _dataActivityDirection
            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value)
            .stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)

    private val _carrierNetworkChangeActive = MutableStateFlow(false)
    override val carrierNetworkChangeActive =
        _carrierNetworkChangeActive
            .logDiffsForTable(
                tableLogBuffer,
                columnPrefix = "",
                columnName = COL_CARRIER_NETWORK_CHANGE,
                _carrierNetworkChangeActive.value
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)

    private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
        MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
    override val resolvedNetworkType =
        _resolvedNetworkType
            .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
            .stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)

    override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS)

    override val dataEnabled = MutableStateFlow(true)

    override val cdmaRoaming = MutableStateFlow(false)

    override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))

    /**
     * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
     * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
     * repository.
     */
    fun processDemoMobileEvent(
        event: FakeNetworkEventModel.Mobile,
        resolvedNetworkType: ResolvedNetworkType,
    ) {
        // This is always true here, because we split out disabled states at the data-source level
        dataEnabled.value = true
        networkName.value = NetworkNameModel.IntentDerived(event.name)

        cdmaRoaming.value = event.roaming
        _isRoaming.value = event.roaming
        // TODO(b/261029387): not yet supported
        _isEmergencyOnly.value = false
        _operatorAlphaShort.value = event.name
        _isInService.value = (event.level ?: 0) > 0
        // TODO(b/261029387): not yet supported
        _isGsm.value = false
        _cdmaLevel.value = event.level ?: 0
        _primaryLevel.value = event.level ?: 0
        // TODO(b/261029387): not yet supported
        _dataConnectionState.value = DataConnectionState.Connected
        _dataActivityDirection.value =
            (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
        _carrierNetworkChangeActive.value = event.carrierNetworkChange
        _resolvedNetworkType.value = resolvedNetworkType
    }

    fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
        // This is always true here, because we split out disabled states at the data-source level
        dataEnabled.value = true
        networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
        numberOfLevels.value = event.numberOfLevels
        cdmaRoaming.value = false
        _primaryLevel.value = event.level
        _cdmaLevel.value = event.level
        _dataActivityDirection.value = event.activity.toMobileDataActivityModel()

        // These fields are always the same for carrier-merged networks
        _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType
        _dataConnectionState.value = DataConnectionState.Connected
        _isRoaming.value = false
        _isEmergencyOnly.value = false
        _operatorAlphaShort.value = null
        _isInService.value = true
        _isGsm.value = false
        _carrierNetworkChangeActive.value = false
    }

    companion object {
        private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
    }
}
+1 −117
Original line number Diff line number Diff line
@@ -17,19 +17,14 @@
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo

import android.content.Context
import android.telephony.CellSignalStrength
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
import android.telephony.TelephonyManager
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.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
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.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -39,8 +34,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.Mobile
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
import javax.inject.Inject
@@ -52,7 +45,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
@@ -191,6 +183,7 @@ constructor(
            DemoMobileConnectionRepository(
                subId,
                tableLogBuffer,
                scope,
            )
        return CacheContainer(repo, lastMobileState = null)
    }
@@ -338,112 +331,3 @@ class CacheContainer(
    /** The last received [Mobile] event. Used when switching from carrier merged back to mobile. */
    var lastMobileState: Mobile?,
)

class DemoMobileConnectionRepository(
    override val subId: Int,
    override val tableLogBuffer: TableLogBuffer,
) : MobileConnectionRepository {
    private val _isEmergencyOnly = MutableStateFlow(false)
    override val isEmergencyOnly = _isEmergencyOnly.asStateFlow()

    private val _isRoaming = MutableStateFlow(false)
    override val isRoaming = _isRoaming.asStateFlow()

    private val _operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
    override val operatorAlphaShort = _operatorAlphaShort.asStateFlow()

    private val _isInService = MutableStateFlow(false)
    override val isInService = _isInService.asStateFlow()

    private val _isGsm = MutableStateFlow(false)
    override val isGsm = _isGsm.asStateFlow()

    private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
    override val cdmaLevel = _cdmaLevel.asStateFlow()

    private val _primaryLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
    override val primaryLevel = _primaryLevel.asStateFlow()

    private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
    override val dataConnectionState = _dataConnectionState.asStateFlow()

    private val _dataActivityDirection =
        MutableStateFlow(
            DataActivityModel(
                hasActivityIn = false,
                hasActivityOut = false,
            )
        )
    override val dataActivityDirection = _dataActivityDirection.asStateFlow()

    private val _carrierNetworkChangeActive = MutableStateFlow(false)
    override val carrierNetworkChangeActive = _carrierNetworkChangeActive.asStateFlow()

    private val _resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
        MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
    override val resolvedNetworkType = _resolvedNetworkType.asStateFlow()

    override val numberOfLevels = MutableStateFlow(MobileConnectionRepository.DEFAULT_NUM_LEVELS)

    override val dataEnabled = MutableStateFlow(true)

    override val cdmaRoaming = MutableStateFlow(false)

    override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))

    /**
     * Process a new demo mobile event. Note that [resolvedNetworkType] must be passed in separately
     * from the event, due to the requirement to reverse the mobile mappings lookup in the top-level
     * repository.
     */
    fun processDemoMobileEvent(
        event: FakeNetworkEventModel.Mobile,
        resolvedNetworkType: ResolvedNetworkType,
    ) {
        // This is always true here, because we split out disabled states at the data-source level
        dataEnabled.value = true
        networkName.value = NetworkNameModel.IntentDerived(event.name)

        cdmaRoaming.value = event.roaming
        _isRoaming.value = event.roaming
        // TODO(b/261029387): not yet supported
        _isEmergencyOnly.value = false
        _operatorAlphaShort.value = event.name
        _isInService.value = (event.level ?: 0) > 0
        // TODO(b/261029387): not yet supported
        _isGsm.value = false
        _cdmaLevel.value = event.level ?: 0
        _primaryLevel.value = event.level ?: 0
        // TODO(b/261029387): not yet supported
        _dataConnectionState.value = DataConnectionState.Connected
        _dataActivityDirection.value =
            (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel()
        _carrierNetworkChangeActive.value = event.carrierNetworkChange
        _resolvedNetworkType.value = resolvedNetworkType
    }

    fun processCarrierMergedEvent(event: FakeWifiEventModel.CarrierMerged) {
        // This is always true here, because we split out disabled states at the data-source level
        dataEnabled.value = true
        networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
        numberOfLevels.value = event.numberOfLevels
        cdmaRoaming.value = false
        _primaryLevel.value = event.level
        _cdmaLevel.value = event.level
        _dataActivityDirection.value = event.activity.toMobileDataActivityModel()

        // These fields are always the same for carrier-merged networks
        _resolvedNetworkType.value = ResolvedNetworkType.CarrierMergedNetworkType
        _dataConnectionState.value = DataConnectionState.Connected
        _isRoaming.value = false
        _isEmergencyOnly.value = false
        _operatorAlphaShort.value = null
        _isInService.value = true
        _isGsm.value = false
        _carrierNetworkChangeActive.value = false
    }

    companion object {
        private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
    }
}
+21 −1
Original line number Diff line number Diff line
@@ -35,8 +35,11 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -122,10 +125,25 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
            assertConnection(underTest, networkModel)
        }

    private fun assertConnection(
    private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
        val job = launch {
            launch { conn.cdmaLevel.collect {} }
            launch { conn.primaryLevel.collect {} }
            launch { conn.dataActivityDirection.collect {} }
            launch { conn.carrierNetworkChangeActive.collect {} }
            launch { conn.isRoaming.collect {} }
            launch { conn.networkName.collect {} }
            launch { conn.isEmergencyOnly.collect {} }
            launch { conn.dataConnectionState.collect {} }
        }
        return job
    }

    private fun TestScope.assertConnection(
        conn: DemoMobileConnectionRepository,
        model: FakeNetworkEventModel
    ) {
        val job = startCollection(underTest)
        when (model) {
            is FakeNetworkEventModel.Mobile -> {
                assertThat(conn.subId).isEqualTo(model.subId)
@@ -148,6 +166,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
            // DemoMobileConnectionsRepositoryTest.kt
            else -> {}
        }

        job.cancel()
    }

    /** Matches [FakeNetworkEventModel] */
+25 −2
Original line number Diff line number Diff line
@@ -39,9 +39,11 @@ import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -523,10 +525,27 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
            job.cancel()
        }

    private fun assertConnection(
    private fun TestScope.startCollection(conn: DemoMobileConnectionRepository): Job {
        val job = launch {
            launch { conn.cdmaLevel.collect {} }
            launch { conn.primaryLevel.collect {} }
            launch { conn.dataActivityDirection.collect {} }
            launch { conn.carrierNetworkChangeActive.collect {} }
            launch { conn.isRoaming.collect {} }
            launch { conn.networkName.collect {} }
            launch { conn.isEmergencyOnly.collect {} }
            launch { conn.dataConnectionState.collect {} }
        }
        return job
    }

    private fun TestScope.assertConnection(
        conn: DemoMobileConnectionRepository,
        model: FakeNetworkEventModel,
    ) {
        val job = startCollection(conn)
        // Assert the fields using the `MutableStateFlow` so that we don't have to start up
        // a collector for every field for every test
        when (model) {
            is FakeNetworkEventModel.Mobile -> {
                assertThat(conn.subId).isEqualTo(model.subId)
@@ -547,12 +566,15 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
            }
            else -> {}
        }

        job.cancel()
    }

    private fun assertCarrierMergedConnection(
    private fun TestScope.assertCarrierMergedConnection(
        conn: DemoMobileConnectionRepository,
        model: FakeWifiEventModel.CarrierMerged,
    ) {
        val job = startCollection(conn)
        assertThat(conn.subId).isEqualTo(model.subscriptionId)
        assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
        assertThat(conn.primaryLevel.value).isEqualTo(model.level)
@@ -561,6 +583,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
        assertThat(conn.isEmergencyOnly.value).isFalse()
        assertThat(conn.isGsm.value).isFalse()
        assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
        job.cancel()
    }
}