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

Commit 4e53da6d authored by Evan Laird's avatar Evan Laird
Browse files

[Sb refactor] Add logging to mobile connections pipeline

Add logging to all inputs into the mobile connections pipeline,
including the TelephonyCallback that is used to calculate most of the
relevant state for an individual icon

Test: MobileConnectionsRepositoryTest
Bug: 238425913
Bug: 240569788
Change-Id: I6eccf2d21f942a19dde8543a7926e3ce1c069db4
parent bcfa7ada
Loading
Loading
Loading
Loading
+71 −1
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.telephony.TelephonyCallback.ServiceStateListener
import android.telephony.TelephonyCallback.SignalStrengthsListener
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel

@@ -79,4 +81,72 @@ data class MobileConnectionModel(
     * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
     */
    val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
)
) : Diffable<MobileConnectionModel> {
    override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) {
        if (prevVal.dataConnectionState != dataConnectionState) {
            row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
        }

        if (prevVal.isEmergencyOnly != isEmergencyOnly) {
            row.logChange(COL_EMERGENCY, isEmergencyOnly)
        }

        if (prevVal.isRoaming != isRoaming) {
            row.logChange(COL_ROAMING, isRoaming)
        }

        if (prevVal.operatorAlphaShort != operatorAlphaShort) {
            row.logChange(COL_OPERATOR, operatorAlphaShort)
        }

        if (prevVal.isGsm != isGsm) {
            row.logChange(COL_IS_GSM, isGsm)
        }

        if (prevVal.cdmaLevel != cdmaLevel) {
            row.logChange(COL_CDMA_LEVEL, cdmaLevel)
        }

        if (prevVal.primaryLevel != primaryLevel) {
            row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
        }

        if (prevVal.dataActivityDirection != dataActivityDirection) {
            row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
        }

        if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) {
            row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
        }

        if (prevVal.resolvedNetworkType != resolvedNetworkType) {
            row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
        }
    }

    override fun logFull(row: TableRowLogger) {
        row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
        row.logChange(COL_EMERGENCY, isEmergencyOnly)
        row.logChange(COL_ROAMING, isRoaming)
        row.logChange(COL_OPERATOR, operatorAlphaShort)
        row.logChange(COL_IS_GSM, isGsm)
        row.logChange(COL_CDMA_LEVEL, cdmaLevel)
        row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
        row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
        row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
        row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
    }

    companion object {
        const val COL_EMERGENCY = "EmergencyOnly"
        const val COL_ROAMING = "Roaming"
        const val COL_OPERATOR = "OperatorName"
        const val COL_IS_GSM = "IsGsm"
        const val COL_CDMA_LEVEL = "CdmaLevel"
        const val COL_PRIMARY_LEVEL = "PrimaryLevel"
        const val COL_CONNECTION_STATE = "ConnectionState"
        const val COL_ACTIVITY_DIRECTION = "DataActivity"
        const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive"
        const val COL_RESOLVED_NETWORK_TYPE = "NetworkType"
    }
}
+29 −3
Original line number Diff line number Diff line
@@ -21,22 +21,48 @@ import android.telephony.TelephonyManager.EXTRA_DATA_SPN
import android.telephony.TelephonyManager.EXTRA_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger

/**
 * Encapsulates the data needed to show a network name for a mobile network. The data is parsed from
 * the intent sent by [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED].
 */
sealed interface NetworkNameModel {
sealed interface NetworkNameModel : Diffable<NetworkNameModel> {
    val name: String

    /** The default name is read from [com.android.internal.R.string.lockscreen_carrier_default] */
    data class Default(override val name: String) : NetworkNameModel
    data class Default(override val name: String) : NetworkNameModel {
        override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) {
            if (prevVal !is Default || prevVal.name != name) {
                row.logChange(COL_NETWORK_NAME, "Default($name)")
            }
        }

        override fun logFull(row: TableRowLogger) {
            row.logChange(COL_NETWORK_NAME, "Default($name)")
        }
    }

    /**
     * This name has been derived from telephony intents. see
     * [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED]
     */
    data class Derived(override val name: String) : NetworkNameModel
    data class Derived(override val name: String) : NetworkNameModel {
        override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) {
            if (prevVal !is Derived || prevVal.name != name) {
                row.logChange(COL_NETWORK_NAME, "Derived($name)")
            }
        }

        override fun logFull(row: TableRowLogger) {
            row.logChange(COL_NETWORK_NAME, "Derived($name)")
        }
    }

    companion object {
        const val COL_NETWORK_NAME = "networkName"
    }
}

fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
+52 −7
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -46,7 +49,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameMo
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
@@ -59,6 +61,7 @@ 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.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
@@ -79,6 +82,7 @@ class MobileConnectionRepositoryImpl(
    mobileMappingsProxy: MobileMappingsProxy,
    bgDispatcher: CoroutineDispatcher,
    logger: ConnectivityPipelineLogger,
    mobileLogger: TableLogBuffer,
    scope: CoroutineScope,
) : MobileConnectionRepository {
    init {
@@ -95,7 +99,6 @@ class MobileConnectionRepositoryImpl(
    override val connectionInfo: StateFlow<MobileConnectionModel> = run {
        var state = MobileConnectionModel()
        conflatedCallbackFlow {
                // TODO (b/240569788): log all of these into the connectivity logger
                val callback =
                    object :
                        TelephonyCallback(),
@@ -106,6 +109,7 @@ class MobileConnectionRepositoryImpl(
                        TelephonyCallback.CarrierNetworkListener,
                        TelephonyCallback.DisplayInfoListener {
                        override fun onServiceStateChanged(serviceState: ServiceState) {
                            logger.logOnServiceStateChanged(serviceState, subId)
                            state =
                                state.copy(
                                    isEmergencyOnly = serviceState.isEmergencyOnly,
@@ -116,6 +120,7 @@ class MobileConnectionRepositoryImpl(
                        }

                        override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
                            logger.logOnSignalStrengthsChanged(signalStrength, subId)
                            val cdmaLevel =
                                signalStrength
                                    .getCellSignalStrengths(CellSignalStrengthCdma::class.java)
@@ -142,12 +147,14 @@ class MobileConnectionRepositoryImpl(
                            dataState: Int,
                            networkType: Int
                        ) {
                            logger.logOnDataConnectionStateChanged(dataState, networkType, subId)
                            state =
                                state.copy(dataConnectionState = dataState.toDataConnectionType())
                            trySend(state)
                        }

                        override fun onDataActivity(direction: Int) {
                            logger.logOnDataActivity(direction, subId)
                            state =
                                state.copy(
                                    dataActivityDirection = direction.toMobileDataActivityModel()
@@ -156,6 +163,7 @@ class MobileConnectionRepositoryImpl(
                        }

                        override fun onCarrierNetworkChange(active: Boolean) {
                            logger.logOnCarrierNetworkChange(active, subId)
                            state = state.copy(carrierNetworkChangeActive = active)
                            trySend(state)
                        }
@@ -163,6 +171,7 @@ class MobileConnectionRepositoryImpl(
                        override fun onDisplayInfoChanged(
                            telephonyDisplayInfo: TelephonyDisplayInfo
                        ) {
                            logger.logOnDisplayInfoChanged(telephonyDisplayInfo, subId)

                            val networkType =
                                if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
@@ -193,7 +202,11 @@ class MobileConnectionRepositoryImpl(
                awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
            }
            .onEach { telephonyCallbackEvent.tryEmit(Unit) }
            .logOutputChange(logger, "MobileSubscriptionModel")
            .logDiffsForTable(
                mobileLogger,
                columnPrefix = "MobileConnection ($subId)",
                initialValue = state,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), state)
    }

@@ -243,19 +256,43 @@ class MobileConnectionRepositoryImpl(
                    intent.toNetworkNameModel(networkNameSeparator) ?: defaultNetworkName
                }
            }
            .distinctUntilChanged()
            .logDiffsForTable(
                mobileLogger,
                columnPrefix = "",
                initialValue = defaultNetworkName,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)

    override val dataEnabled: StateFlow<Boolean> =
    override val dataEnabled: StateFlow<Boolean> = run {
        val initial = dataConnectionAllowed()
        telephonyPollingEvent
            .mapLatest { dataConnectionAllowed() }
            .stateIn(scope, SharingStarted.WhileSubscribed(), dataConnectionAllowed())
            .distinctUntilChanged()
            .logDiffsForTable(
                mobileLogger,
                columnPrefix = "",
                columnName = "dataEnabled",
                initialValue = initial,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
    }

    private fun dataConnectionAllowed(): Boolean = telephonyManager.isDataConnectionAllowed

    override val isDefaultDataSubscription: StateFlow<Boolean> =
    override val isDefaultDataSubscription: StateFlow<Boolean> = run {
        val initialValue = defaultDataSubId.value == subId
        defaultDataSubId
            .mapLatest { it == subId }
            .stateIn(scope, SharingStarted.WhileSubscribed(), defaultDataSubId.value == subId)
            .distinctUntilChanged()
            .logDiffsForTable(
                mobileLogger,
                columnPrefix = "",
                columnName = "isDefaultDataSub",
                initialValue = initialValue,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), initialValue)
    }

    class Factory
    @Inject
@@ -266,6 +303,7 @@ class MobileConnectionRepositoryImpl(
        private val logger: ConnectivityPipelineLogger,
        private val globalSettings: GlobalSettings,
        private val mobileMappingsProxy: MobileMappingsProxy,
        private val logFactory: TableLogBufferFactory,
        @Background private val bgDispatcher: CoroutineDispatcher,
        @Application private val scope: CoroutineScope,
    ) {
@@ -276,6 +314,8 @@ class MobileConnectionRepositoryImpl(
            defaultDataSubId: StateFlow<Int>,
            globalMobileDataSettingChangedEvent: Flow<Unit>,
        ): MobileConnectionRepository {
            val mobileLogger = logFactory.create(tableBufferLogName(subId), 100)

            return MobileConnectionRepositoryImpl(
                context,
                subId,
@@ -289,8 +329,13 @@ class MobileConnectionRepositoryImpl(
                mobileMappingsProxy,
                bgDispatcher,
                logger,
                mobileLogger,
                scope,
            )
        }
    }

    companion object {
        fun tableBufferLogName(subId: Int): String = "MobileConnectionLog [$subId]"
    }
}
+36 −19
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -120,6 +121,7 @@ constructor(
                awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
            }
            .mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
            .logInputChange(logger, "onSubscriptionsChanged")
            .onEach { infos -> dropUnusedReposFromCache(infos) }
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())

@@ -136,6 +138,8 @@ constructor(
                telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
                awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
            }
            .distinctUntilChanged()
            .logInputChange(logger, "onActiveDataSubscriptionIdChanged")
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)

    private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
@@ -149,6 +153,7 @@ constructor(
                intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
            }
            .distinctUntilChanged()
            .logInputChange(logger, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED")
            .onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
            .stateIn(
                scope,
@@ -157,13 +162,15 @@ constructor(
            )

    private val carrierConfigChangedEvent =
        broadcastDispatcher.broadcastFlow(
            IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)
        )
        broadcastDispatcher
            .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED))
            .logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED")

    override val defaultDataSubRatConfig: StateFlow<Config> =
        merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
            .mapLatest { Config.readConfig(context) }
            .distinctUntilChanged()
            .logInputChange(logger, "defaultDataSubRatConfig")
            .stateIn(
                scope,
                SharingStarted.WhileSubscribed(),
@@ -171,10 +178,16 @@ constructor(
            )

    override val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>> =
        defaultDataSubRatConfig.map { mobileMappingsProxy.mapIconSets(it) }
        defaultDataSubRatConfig
            .map { mobileMappingsProxy.mapIconSets(it) }
            .distinctUntilChanged()
            .logInputChange(logger, "defaultMobileIconMapping")

    override val defaultMobileIconGroup: Flow<MobileIconGroup> =
        defaultDataSubRatConfig.map { mobileMappingsProxy.getDefaultIcons(it) }
        defaultDataSubRatConfig
            .map { mobileMappingsProxy.getDefaultIcons(it) }
            .distinctUntilChanged()
            .logInputChange(logger, "defaultMobileIconGroup")

    override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
        if (!isValidSubId(subId)) {
@@ -191,7 +204,8 @@ constructor(
     * In single-SIM devices, the [MOBILE_DATA] setting is phone-wide. For multi-SIM, the individual
     * connection repositories also observe the URI for [MOBILE_DATA] + subId.
     */
    override val globalMobileDataSettingChangedEvent: Flow<Unit> = conflatedCallbackFlow {
    override val globalMobileDataSettingChangedEvent: Flow<Unit> =
        conflatedCallbackFlow {
                val observer =
                    object : ContentObserver(null) {
                        override fun onChange(selfChange: Boolean) {
@@ -207,6 +221,7 @@ constructor(

                awaitClose { context.contentResolver.unregisterContentObserver(observer) }
            }
            .logInputChange(logger, "globalMobileDataSettingChangedEvent")

    @SuppressLint("MissingPermission")
    override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
@@ -236,6 +251,8 @@ constructor(

                awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
            }
            .distinctUntilChanged()
            .logInputChange(logger, "defaultMobileNetworkConnectivity")
            .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())

    private fun isValidSubId(subId: Int): Boolean {
+111 −55
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ package com.android.systemui.statusbar.pipeline.shared

import android.net.Network
import android.net.NetworkCapabilities
import com.android.systemui.log.dagger.StatusBarConnectivityLog
import android.telephony.ServiceState
import android.telephony.SignalStrength
import android.telephony.TelephonyDisplayInfo
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.StatusBarConnectivityLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString
@@ -28,7 +31,9 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onEach

@SysUISingleton
class ConnectivityPipelineLogger @Inject constructor(
class ConnectivityPipelineLogger
@Inject
constructor(
    @StatusBarConnectivityLog private val buffer: LogBuffer,
) {
    /**
@@ -37,17 +42,10 @@ class ConnectivityPipelineLogger @Inject constructor(
     * Use this method for inputs that don't have any extra information besides their callback name.
     */
    fun logInputChange(callbackName: String) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            { str1 = callbackName },
            { "Input: $str1" }
        )
        buffer.log(SB_LOGGING_TAG, LogLevel.INFO, { str1 = callbackName }, { "Input: $str1" })
    }

    /**
     * Logs a change in one of the **raw inputs** to the connectivity pipeline.
     */
    /** Logs a change in one of the **raw inputs** to the connectivity pipeline. */
    fun logInputChange(callbackName: String, changeInfo: String?) {
        buffer.log(
            SB_LOGGING_TAG,
@@ -56,15 +54,11 @@ class ConnectivityPipelineLogger @Inject constructor(
                str1 = callbackName
                str2 = changeInfo
            },
                {
                    "Input: $str1: $str2"
                }
            { "Input: $str1: $str2" }
        )
    }

    /**
     * Logs a **data transformation** that we performed within the connectivity pipeline.
     */
    /** Logs a **data transformation** that we performed within the connectivity pipeline. */
    fun logTransformation(transformationName: String, oldValue: Any?, newValue: Any?) {
        if (oldValue == newValue) {
            buffer.log(
@@ -74,9 +68,7 @@ class ConnectivityPipelineLogger @Inject constructor(
                    str1 = transformationName
                    str2 = oldValue.toString()
                },
                {
                    "Transform: $str1: $str2 (transformation didn't change it)"
                }
                { "Transform: $str1: $str2 (transformation didn't change it)" }
            )
        } else {
            buffer.log(
@@ -87,16 +79,12 @@ class ConnectivityPipelineLogger @Inject constructor(
                    str2 = oldValue.toString()
                    str3 = newValue.toString()
                },
                {
                    "Transform: $str1: $str2 -> $str3"
                }
                { "Transform: $str1: $str2 -> $str3" }
            )
        }
    }

    /**
     * Logs a change in one of the **outputs** to the connectivity pipeline.
     */
    /** Logs a change in one of the **outputs** to the connectivity pipeline. */
    fun logOutputChange(outputParamName: String, changeInfo: String) {
        buffer.log(
            SB_LOGGING_TAG,
@@ -105,9 +93,7 @@ class ConnectivityPipelineLogger @Inject constructor(
                str1 = outputParamName
                str2 = changeInfo
            },
                {
                    "Output: $str1: $str2"
                }
            { "Output: $str1: $str2" }
        )
    }

@@ -119,31 +105,101 @@ class ConnectivityPipelineLogger @Inject constructor(
                int1 = network.getNetId()
                str1 = networkCapabilities.toString()
            },
            { "onCapabilitiesChanged: net=$int1 capabilities=$str1" }
        )
    }

    fun logOnLost(network: Network) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            { int1 = network.getNetId() },
            { "onLost: net=$int1" }
        )
    }

    fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                int1 = subId
                bool1 = serviceState.isEmergencyOnly
                bool2 = serviceState.roaming
                str1 = serviceState.operatorAlphaShort
            },
            {
                "onCapabilitiesChanged: net=$int1 capabilities=$str1"
                "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
                    " operator=$str1"
            }
        )
    }

    fun logOnLost(network: Network) {
    fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                int1 = network.getNetId()
                int1 = subId
                str1 = signalStrength.toString()
            },
            { "onSignalStrengthsChanged: subId=$int1 strengths=$str1" }
        )
    }

    fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                "onLost: net=$int1"
                int1 = subId
                int2 = dataState
                str1 = networkType.toString()
            },
            { "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" },
        )
    }

    fun logOnDataActivity(direction: Int, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                int1 = subId
                int2 = direction
            },
            { "onDataActivity: subId=$int1 direction=$int2" },
        )
    }

    fun logOnCarrierNetworkChange(active: Boolean, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                int1 = subId
                bool1 = active
            },
            { "onCarrierNetworkChange: subId=$int1 active=$bool1" },
        )
    }

    fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
        buffer.log(
            SB_LOGGING_TAG,
            LogLevel.INFO,
            {
                int1 = subId
                str1 = displayInfo.toString()
            },
            { "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" },
        )
    }

    companion object {
        const val SB_LOGGING_TAG = "SbConnectivity"

        /**
         * Log a change in one of the **inputs** to the connectivity pipeline.
         */
        /** Log a change in one of the **inputs** to the connectivity pipeline. */
        fun Flow<Unit>.logInputChange(
            logger: ConnectivityPipelineLogger,
            inputParamName: String,
Loading