summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Laird <evanlaird@google.com> 2022-12-15 17:56:32 -0500
committer Evan Laird <evanlaird@google.com> 2022-12-20 14:15:36 -0500
commit4e53da6d8d0480de15dc3f05e237f0e5efc39df1 (patch)
tree2d79bcc719382b74d929c6a4682e718ca4a32346
parentbcfa7ada7cb402ba967cd22a9a2e4f5e7a7bd570 (diff)
[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
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt166
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt36
8 files changed, 431 insertions, 85 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
index 6c37f94007cb..1aa954ff48cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
@@ -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"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index a8cf35ad3029..c50d82a66c76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -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? {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 7e9a9cea9b95..50b29f4c9028 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -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]"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index a9b3d18774fd..d407abeb2315 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -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,22 +204,24 @@ 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 {
- val observer =
- object : ContentObserver(null) {
- override fun onChange(selfChange: Boolean) {
- trySend(Unit)
- }
- }
+ override val globalMobileDataSettingChangedEvent: Flow<Unit> =
+ conflatedCallbackFlow {
+ val observer =
+ object : ContentObserver(null) {
+ override fun onChange(selfChange: Boolean) {
+ trySend(Unit)
+ }
+ }
- globalSettings.registerContentObserver(
- globalSettings.getUriFor(MOBILE_DATA),
- true,
- observer
- )
+ globalSettings.registerContentObserver(
+ globalSettings.getUriFor(MOBILE_DATA),
+ true,
+ observer
+ )
- awaitClose { context.contentResolver.unregisterContentObserver(observer) }
- }
+ 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 {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
index d3cf32fb44ce..d3ff3573dae2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
@@ -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,34 +42,23 @@ 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,
- LogLevel.INFO,
- {
- str1 = callbackName
- str2 = changeInfo
- },
- {
- "Input: $str1: $str2"
- }
+ SB_LOGGING_TAG,
+ LogLevel.INFO,
+ {
+ str1 = callbackName
+ str2 = changeInfo
+ },
+ { "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,27 +79,21 @@ 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,
- LogLevel.INFO,
- {
- str1 = outputParamName
- str2 = changeInfo
- },
- {
- "Output: $str1: $str2"
- }
+ SB_LOGGING_TAG,
+ LogLevel.INFO,
+ {
+ str1 = outputParamName
+ str2 = changeInfo
+ },
+ { "Output: $str1: $str2" }
)
}
@@ -119,9 +105,7 @@ class ConnectivityPipelineLogger @Inject constructor(
int1 = network.getNetId()
str1 = networkCapabilities.toString()
},
- {
- "onCapabilitiesChanged: net=$int1 capabilities=$str1"
- }
+ { "onCapabilitiesChanged: net=$int1 capabilities=$str1" }
)
}
@@ -129,21 +113,93 @@ class ConnectivityPipelineLogger @Inject constructor(
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 = network.getNetId()
+ int1 = subId
+ bool1 = serviceState.isEmergencyOnly
+ bool2 = serviceState.roaming
+ str1 = serviceState.operatorAlphaShort
},
{
- "onLost: net=$int1"
+ "onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
+ " operator=$str1"
}
)
}
+ fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) {
+ buffer.log(
+ SB_LOGGING_TAG,
+ LogLevel.INFO,
+ {
+ 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,
+ {
+ 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,
@@ -155,26 +211,26 @@ class ConnectivityPipelineLogger @Inject constructor(
* Log a change in one of the **inputs** to the connectivity pipeline.
*
* @param prettyPrint an optional function to transform the value into a readable string.
- * [toString] is used if no custom function is provided.
+ * [toString] is used if no custom function is provided.
*/
fun <T> Flow<T>.logInputChange(
logger: ConnectivityPipelineLogger,
inputParamName: String,
prettyPrint: (T) -> String = { it.toString() }
): Flow<T> {
- return this.onEach {logger.logInputChange(inputParamName, prettyPrint(it)) }
+ return this.onEach { logger.logInputChange(inputParamName, prettyPrint(it)) }
}
/**
* Log a change in one of the **outputs** to the connectivity pipeline.
*
* @param prettyPrint an optional function to transform the value into a readable string.
- * [toString] is used if no custom function is provided.
+ * [toString] is used if no custom function is provided.
*/
fun <T> Flow<T>.logOutputChange(
- logger: ConnectivityPipelineLogger,
- outputParamName: String,
- prettyPrint: (T) -> String = { it.toString() }
+ logger: ConnectivityPipelineLogger,
+ outputParamName: String,
+ prettyPrint: (T) -> String = { it.toString() }
): Flow<T> {
return this.onEach { logger.logOutputChange(outputParamName, prettyPrint(it)) }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
new file mode 100644
index 000000000000..f822ba0f0a62
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
@@ -0,0 +1,93 @@
+/*
+ * 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
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableRowLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_IS_GSM
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_RESOLVED_NETWORK_TYPE
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ROAMING
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@SmallTest
+class MobileConnectionModelTest : SysuiTestCase() {
+
+ @Test
+ fun `log diff - initial log contains all columns`() {
+ val logger = TestLogger()
+ val connection = MobileConnectionModel()
+
+ connection.logFull(logger)
+
+ assertThat(logger.changes)
+ .contains(Pair(COL_EMERGENCY, connection.isEmergencyOnly.toString()))
+ assertThat(logger.changes).contains(Pair(COL_ROAMING, connection.isRoaming.toString()))
+ assertThat(logger.changes)
+ .contains(Pair(COL_OPERATOR, connection.operatorAlphaShort.toString()))
+ assertThat(logger.changes).contains(Pair(COL_IS_GSM, connection.isGsm.toString()))
+ assertThat(logger.changes).contains(Pair(COL_CDMA_LEVEL, connection.cdmaLevel.toString()))
+ assertThat(logger.changes)
+ .contains(Pair(COL_PRIMARY_LEVEL, connection.primaryLevel.toString()))
+ assertThat(logger.changes)
+ .contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString()))
+ assertThat(logger.changes)
+ .contains(Pair(COL_ACTIVITY_DIRECTION, connection.dataActivityDirection.toString()))
+ assertThat(logger.changes)
+ .contains(
+ Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString())
+ )
+ assertThat(logger.changes)
+ .contains(Pair(COL_RESOLVED_NETWORK_TYPE, connection.resolvedNetworkType.toString()))
+ }
+
+ @Test
+ fun `log diff - primary level changes - only level is logged`() {
+ val logger = TestLogger()
+ val connectionOld = MobileConnectionModel(primaryLevel = 1)
+
+ val connectionNew = MobileConnectionModel(primaryLevel = 2)
+
+ connectionNew.logDiffs(connectionOld, logger)
+
+ assertThat(logger.changes).isEqualTo(listOf(Pair(COL_PRIMARY_LEVEL, "2")))
+ }
+
+ private class TestLogger : TableRowLogger {
+ val changes = mutableListOf<Pair<String, String>>()
+
+ override fun logChange(columnName: String, value: String?) {
+ changes.add(Pair(columnName, value.toString()))
+ }
+
+ override fun logChange(columnName: String, value: Int) {
+ changes.add(Pair(columnName, value.toString()))
+ }
+
+ override fun logChange(columnName: String, value: Boolean) {
+ changes.add(Pair(columnName, value.toString()))
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index 7fa80653f29c..9a3e95826c84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -50,6 +50,7 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
@@ -90,6 +91,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
@Mock private lateinit var telephonyManager: TelephonyManager
@Mock private lateinit var logger: ConnectivityPipelineLogger
+ @Mock private lateinit var tableLogger: TableLogBuffer
private val scope = CoroutineScope(IMMEDIATE)
private val mobileMappings = FakeMobileMappingsProxy()
@@ -116,6 +118,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
mobileMappings,
IMMEDIATE,
logger,
+ tableLogger,
scope,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 3cc1e8b74668..b8cd7a4f6e0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -34,12 +34,15 @@ import com.android.internal.telephony.PhoneConstants
import com.android.settingslib.R
import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.TableLogBufferFactory
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.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.FakeSettings
@@ -57,6 +60,7 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -72,6 +76,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
@Mock private lateinit var subscriptionManager: SubscriptionManager
@Mock private lateinit var telephonyManager: TelephonyManager
@Mock private lateinit var logger: ConnectivityPipelineLogger
+ @Mock private lateinit var logBufferFactory: TableLogBufferFactory
private val mobileMappings = FakeMobileMappingsProxy()
@@ -89,6 +94,10 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
}
}
+ whenever(logBufferFactory.create(anyString(), anyInt())).thenAnswer { _ ->
+ mock<TableLogBuffer>()
+ }
+
connectionFactory =
MobileConnectionRepositoryImpl.Factory(
fakeBroadcastDispatcher,
@@ -99,6 +108,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
logger = logger,
mobileMappingsProxy = mobileMappings,
scope = scope,
+ logFactory = logBufferFactory,
)
underTest =
@@ -271,6 +281,32 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
}
@Test
+ fun `connection repository - log buffer contains sub id in its name`() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.subscriptions.launchIn(this)
+
+ whenever(subscriptionManager.completeActiveSubscriptionInfoList)
+ .thenReturn(listOf(SUB_1, SUB_2))
+ getSubscriptionCallback().onSubscriptionsChanged()
+
+ // Get repos to trigger creation
+ underTest.getRepoForSubId(SUB_1_ID)
+ verify(logBufferFactory)
+ .create(
+ eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_1_ID)),
+ anyInt(),
+ )
+ underTest.getRepoForSubId(SUB_2_ID)
+ verify(logBufferFactory)
+ .create(
+ eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_2_ID)),
+ anyInt(),
+ )
+
+ job.cancel()
+ }
+
+ @Test
fun testDefaultDataSubId_updatesOnBroadcast() =
runBlocking(IMMEDIATE) {
var latest: Int? = null