Merge "[People Service] Re-order clean-up to only occur once per shortcuts update" into tm-qpr-dev
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8be5998..9a9f510 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2258,7 +2258,7 @@
 
     <!-- Shows in a dialog presented to the user to authorize this app to display a Device controls
          panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
-    <string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+    <string name="controls_panel_authorization"><xliff:g id="appName" example="My app">%s</xliff:g>can choose which controls and content show here.</string>
 
     <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
          controls panel [CHAR LIMIT=NONE] -->
@@ -2318,7 +2318,7 @@
     <!-- Title of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
     <string name="controls_settings_trivial_controls_dialog_title">Control devices from lock screen?</string>
     <!-- Message of the dialog to control certain devices from lock screen without auth [CHAR LIMIT=NONE] -->
-    <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet.\n\nYour device app determines which devices can be controlled in this way.</string>
+    <string name="controls_settings_trivial_controls_dialog_message">You can control some devices without unlocking your phone or tablet. Your device app determines which devices can be controlled in this way.</string>
     <!-- Neutral button title of the controls dialog [CHAR LIMIT=NONE] -->
     <string name="controls_settings_dialog_neutral_button">No thanks</string>
     <!-- Positive button title of the controls dialog  [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 92e0c85..b0389b5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -239,6 +239,8 @@
                         data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
             if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
                 // TODO also check for a media button receiver intended for restarting (b/154127084)
+                // Set null action to prevent additional attempts to connect
+                mediaDataManager.setResumeAction(key, null)
                 Log.d(TAG, "Checking for service component for " + data.packageName)
                 val pm = context.packageManager
                 val serviceIntent = Intent(MediaBrowserService.SERVICE_INTERFACE)
@@ -249,9 +251,6 @@
                     backgroundExecutor.execute {
                         tryUpdateResumptionList(key, inf!!.get(0).componentInfo.componentName)
                     }
-                } else {
-                    // No service found
-                    mediaDataManager.setResumeAction(key, null)
                 }
             }
         }
@@ -263,8 +262,6 @@
      */
     private fun tryUpdateResumptionList(key: String, componentName: ComponentName) {
         Log.d(TAG, "Testing if we can connect to $componentName")
-        // Set null action to prevent additional attempts to connect
-        mediaDataManager.setResumeAction(key, null)
         mediaBrowser =
             mediaBrowserFactory.create(
                 object : ResumeMediaBrowser.Callback() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
index 3493b24..d460b5b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowser.java
@@ -85,16 +85,13 @@
      * ResumeMediaBrowser#disconnect will be called automatically with this function.
      */
     public void findRecentMedia() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(
+        MediaBrowser browser = mBrowserFactory.create(
                 mComponentName,
                 mConnectionCallback,
                 rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "findRecentMedia");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "findRecentMedia");
     }
 
     private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
@@ -202,6 +199,21 @@
     };
 
     /**
+     * Connect using a new media browser. Disconnects the existing browser first, if it exists.
+     * @param browser media browser to connect
+     * @param reason Reason to log for connection
+     */
+    private void connectBrowser(MediaBrowser browser, String reason) {
+        mLogger.logConnection(mComponentName, reason);
+        disconnect();
+        mMediaBrowser = browser;
+        if (browser != null) {
+            browser.connect();
+        }
+        updateMediaController();
+    }
+
+    /**
      * Disconnect the media browser. This should be done after callbacks have completed to
      * disconnect from the media browser service.
      */
@@ -222,10 +234,9 @@
      * getting a media update from the app
      */
     public void restart() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(mComponentName,
+        MediaBrowser browser = mBrowserFactory.create(mComponentName,
                 new MediaBrowser.ConnectionCallback() {
                     @Override
                     public void onConnected() {
@@ -265,9 +276,7 @@
                         disconnect();
                     }
                 }, rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "restart");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "restart");
     }
 
     @VisibleForTesting
@@ -305,16 +314,13 @@
      * ResumeMediaBrowser#disconnect should be called after this to ensure the connection is closed.
      */
     public void testConnection() {
-        disconnect();
         Bundle rootHints = new Bundle();
         rootHints.putBoolean(MediaBrowserService.BrowserRoot.EXTRA_RECENT, true);
-        mMediaBrowser = mBrowserFactory.create(
+        MediaBrowser browser = mBrowserFactory.create(
                 mComponentName,
                 mConnectionCallback,
                 rootHints);
-        updateMediaController();
-        mLogger.logConnection(mComponentName, "testConnection");
-        mMediaBrowser.connect();
+        connectBrowser(browser, "testConnection");
     }
 
     /** Updates mMediaController based on our current browser values. */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 8721d71..557e95c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -419,6 +419,10 @@
             return;
         }
 
+        mScreenBitmap = screenshot.getBitmap();
+        String oldPackageName = mPackageName;
+        mPackageName = screenshot.getPackageNameString();
+
         if (!isUserSetupComplete(Process.myUserHandle())) {
             Log.w(TAG, "User setup not complete, displaying toast only");
             // User setup isn't complete, so we don't want to show any UI beyond a toast, as editing
@@ -433,10 +437,6 @@
         mScreenshotTakenInPortrait =
                 mContext.getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT;
 
-        String oldPackageName = mPackageName;
-        mPackageName = screenshot.getPackageNameString();
-
-        mScreenBitmap = screenshot.getBitmap();
         // Optimizations
         mScreenBitmap.setHasAlpha(false);
         mScreenBitmap.prepareToDraw();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
index 85729c1..19f0242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/DataConnectionState.kt
@@ -24,9 +24,11 @@
 import android.telephony.TelephonyManager.DATA_SUSPENDED
 import android.telephony.TelephonyManager.DATA_UNKNOWN
 import android.telephony.TelephonyManager.DataState
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
 
 /** Internal enum representation of the telephony data connection states */
-enum class DataConnectionState {
+enum class DataConnectionState : Diffable<DataConnectionState> {
     Connected,
     Connecting,
     Disconnected,
@@ -34,7 +36,17 @@
     Suspended,
     HandoverInProgress,
     Unknown,
-    Invalid,
+    Invalid;
+
+    override fun logDiffs(prevVal: DataConnectionState, row: TableRowLogger) {
+        if (prevVal != this) {
+            row.logChange(COL_CONNECTION_STATE, name)
+        }
+    }
+
+    companion object {
+        private const val COL_CONNECTION_STATE = "connectionState"
+    }
 }
 
 fun @receiver:DataState Int.toDataConnectionType(): DataConnectionState =
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
deleted file mode 100644
index ed7f60b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModel.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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 android.annotation.IntRange
-import android.telephony.CellSignalStrength
-import android.telephony.TelephonyCallback.CarrierNetworkListener
-import android.telephony.TelephonyCallback.DataActivityListener
-import android.telephony.TelephonyCallback.DataConnectionStateListener
-import android.telephony.TelephonyCallback.DisplayInfoListener
-import android.telephony.TelephonyCallback.ServiceStateListener
-import android.telephony.TelephonyCallback.SignalStrengthsListener
-import android.telephony.TelephonyDisplayInfo
-import android.telephony.TelephonyManager
-import androidx.annotation.VisibleForTesting
-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
-
-/**
- * Data class containing all of the relevant information for a particular line of service, known as
- * a Subscription in the telephony world. These models are the result of a single telephony listener
- * which has many callbacks which each modify some particular field on this object.
- *
- * The design goal here is to de-normalize fields from the system into our model fields below. So
- * any new field that needs to be tracked should be copied into this data class rather than
- * threading complex system objects through the pipeline.
- */
-data class MobileConnectionModel(
-    /** Fields below are from [ServiceStateListener.onServiceStateChanged] */
-    val isEmergencyOnly: Boolean = false,
-    val isRoaming: Boolean = false,
-    /**
-     * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
-     * current registered operator name in short alphanumeric format. In some cases this name might
-     * be preferred over other methods of calculating the network name
-     */
-    val operatorAlphaShort: String? = null,
-
-    /**
-     * TODO (b/263167683): Clarify this field
-     *
-     * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
-     * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
-     * connection to be in-service if either the voice registration state is IN_SERVICE or the data
-     * registration state is IN_SERVICE and NOT IWLAN.
-     */
-    val isInService: Boolean = false,
-
-    /** Fields below from [SignalStrengthsListener.onSignalStrengthsChanged] */
-    val isGsm: Boolean = false,
-    @IntRange(from = 0, to = 4)
-    val cdmaLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
-    @IntRange(from = 0, to = 4)
-    val primaryLevel: Int = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN,
-
-    /** Fields below from [DataConnectionStateListener.onDataConnectionStateChanged] */
-    val dataConnectionState: DataConnectionState = Disconnected,
-
-    /**
-     * Fields below from [DataActivityListener.onDataActivity]. See [TelephonyManager] for the
-     * values
-     */
-    val dataActivityDirection: DataActivityModel =
-        DataActivityModel(
-            hasActivityIn = false,
-            hasActivityOut = false,
-        ),
-
-    /** Fields below from [CarrierNetworkListener.onCarrierNetworkChange] */
-    val carrierNetworkChangeActive: Boolean = false,
-
-    /** Fields below from [DisplayInfoListener.onDisplayInfoChanged]. */
-
-    /**
-     * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
-     * [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.name)
-        }
-
-        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.isInService != isInService) {
-            row.logChange(COL_IS_IN_SERVICE, isInService)
-        }
-
-        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.hasActivityIn != dataActivityDirection.hasActivityIn) {
-            row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
-        }
-
-        if (prevVal.dataActivityDirection.hasActivityOut != dataActivityDirection.hasActivityOut) {
-            row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
-        }
-
-        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.name)
-        row.logChange(COL_EMERGENCY, isEmergencyOnly)
-        row.logChange(COL_ROAMING, isRoaming)
-        row.logChange(COL_OPERATOR, operatorAlphaShort)
-        row.logChange(COL_IS_IN_SERVICE, isInService)
-        row.logChange(COL_IS_GSM, isGsm)
-        row.logChange(COL_CDMA_LEVEL, cdmaLevel)
-        row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
-        row.logChange(COL_ACTIVITY_DIRECTION_IN, dataActivityDirection.hasActivityIn)
-        row.logChange(COL_ACTIVITY_DIRECTION_OUT, dataActivityDirection.hasActivityOut)
-        row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
-        row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
-    }
-
-    @VisibleForTesting
-    companion object {
-        const val COL_EMERGENCY = "EmergencyOnly"
-        const val COL_ROAMING = "Roaming"
-        const val COL_OPERATOR = "OperatorName"
-        const val COL_IS_IN_SERVICE = "IsInService"
-        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_IN = "DataActivity.In"
-        const val COL_ACTIVITY_DIRECTION_OUT = "DataActivity.Out"
-        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/ResolvedNetworkType.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
index 5562e73..cf7a313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/ResolvedNetworkType.kt
@@ -17,8 +17,12 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.model
 
 import android.telephony.Annotation.NetworkType
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import com.android.settingslib.SignalIcon
+import com.android.settingslib.mobile.MobileMappings
 import com.android.settingslib.mobile.TelephonyIcons
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 
 /**
@@ -26,11 +30,19 @@
  * on whether or not the display info contains an override type, we may have to call different
  * methods on [MobileMappingsProxy] to generate an icon lookup key.
  */
-sealed interface ResolvedNetworkType {
+sealed interface ResolvedNetworkType : Diffable<ResolvedNetworkType> {
     val lookupKey: String
 
+    override fun logDiffs(prevVal: ResolvedNetworkType, row: TableRowLogger) {
+        if (prevVal != this) {
+            row.logChange(COL_NETWORK_TYPE, this.toString())
+        }
+    }
+
     object UnknownNetworkType : ResolvedNetworkType {
-        override val lookupKey: String = "unknown"
+        override val lookupKey: String = MobileMappings.toIconKey(NETWORK_TYPE_UNKNOWN)
+
+        override fun toString(): String = "Unknown"
     }
 
     data class DefaultNetworkType(
@@ -47,5 +59,11 @@
         override val lookupKey: String = "cwf"
 
         val iconGroupOverride: SignalIcon.MobileIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI
+
+        override fun toString(): String = "CarrierMerged"
+    }
+
+    companion object {
+        private const val COL_NETWORK_TYPE = "networkType"
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
index 6187f64..90c32dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt
@@ -17,11 +17,12 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
 import android.telephony.SubscriptionInfo
-import android.telephony.TelephonyCallback
 import android.telephony.TelephonyManager
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+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.shared.data.model.DataActivityModel
 import kotlinx.coroutines.flow.StateFlow
 
 /**
@@ -45,11 +46,57 @@
      */
     val tableLogBuffer: TableLogBuffer
 
+    /** True if the [android.telephony.ServiceState] says this connection is emergency calls only */
+    val isEmergencyOnly: StateFlow<Boolean>
+
+    /** True if [android.telephony.ServiceState] says we are roaming */
+    val isRoaming: StateFlow<Boolean>
+
     /**
-     * A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
-     * listener + model.
+     * See [android.telephony.ServiceState.getOperatorAlphaShort], this value is defined as the
+     * current registered operator name in short alphanumeric format. In some cases this name might
+     * be preferred over other methods of calculating the network name
      */
-    val connectionInfo: StateFlow<MobileConnectionModel>
+    val operatorAlphaShort: StateFlow<String?>
+
+    /**
+     * TODO (b/263167683): Clarify this field
+     *
+     * This check comes from [com.android.settingslib.Utils.isInService]. It is intended to be a
+     * mapping from a ServiceState to a notion of connectivity. Notably, it will consider a
+     * connection to be in-service if either the voice registration state is IN_SERVICE or the data
+     * registration state is IN_SERVICE and NOT IWLAN.
+     */
+    val isInService: StateFlow<Boolean>
+
+    /** True if [android.telephony.SignalStrength] told us that this connection is using GSM */
+    val isGsm: StateFlow<Boolean>
+
+    /**
+     * There is still specific logic in the pipeline that calls out CDMA level explicitly. This
+     * field is not completely orthogonal to [primaryLevel], because CDMA could be primary.
+     */
+    // @IntRange(from = 0, to = 4)
+    val cdmaLevel: StateFlow<Int>
+
+    /** [android.telephony.SignalStrength]'s concept of the overall signal level */
+    // @IntRange(from = 0, to = 4)
+    val primaryLevel: StateFlow<Int>
+
+    /** The current data connection state. See [DataConnectionState] */
+    val dataConnectionState: StateFlow<DataConnectionState>
+
+    /** The current data activity direction. See [DataActivityModel] */
+    val dataActivityDirection: StateFlow<DataActivityModel>
+
+    /** True if there is currently a carrier network change in process */
+    val carrierNetworkChangeActive: StateFlow<Boolean>
+
+    /**
+     * [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
+     * [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
+     */
+    val resolvedNetworkType: StateFlow<ResolvedNetworkType>
 
     /** The total number of levels. Used with [SignalDrawable]. */
     val numberOfLevels: StateFlow<Int>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
new file mode 100644
index 0000000..809772e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
@@ -0,0 +1,231 @@
+/*
+ * 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"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index e924832..3cafb73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -18,30 +18,22 @@
 
 import android.content.Context
 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
-import android.telephony.TelephonyManager.DATA_ACTIVITY_NONE
 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.MobileConnectionModel
 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
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 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.CarrierMergedConnectionRepository.Companion.createCarrierMergedConnectionModel
 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.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
@@ -183,7 +175,7 @@
     private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
         val tableLogBuffer =
             logFactory.getOrCreate(
-                "DemoMobileConnectionLog [$subId]",
+                "DemoMobileConnectionLog[$subId]",
                 MOBILE_CONNECTION_BUFFER_SIZE,
             )
 
@@ -191,6 +183,7 @@
             DemoMobileConnectionRepository(
                 subId,
                 tableLogBuffer,
+                scope,
             )
         return CacheContainer(repo, lastMobileState = null)
     }
@@ -237,23 +230,18 @@
         }
     }
 
-    private fun processEnabledMobileState(state: Mobile) {
+    private fun processEnabledMobileState(event: Mobile) {
         // get or create the connection repo, and set its values
-        val subId = state.subId ?: DEFAULT_SUB_ID
+        val subId = event.subId ?: DEFAULT_SUB_ID
         maybeCreateSubscription(subId)
 
         val connection = getRepoForSubId(subId)
-        connectionRepoCache[subId]?.lastMobileState = state
+        connectionRepoCache[subId]?.lastMobileState = event
 
         // TODO(b/261029387): until we have a command, use the most recent subId
         defaultDataSubId.value = subId
 
-        // This is always true here, because we split out disabled states at the data-source level
-        connection.dataEnabled.value = true
-        connection.networkName.value = NetworkNameModel.IntentDerived(state.name)
-
-        connection.cdmaRoaming.value = state.roaming
-        connection.connectionInfo.value = state.toMobileConnectionModel()
+        connection.processDemoMobileEvent(event, event.dataType.toResolvedNetworkType())
     }
 
     private fun processCarrierMergedWifiState(event: FakeWifiEventModel.CarrierMerged) {
@@ -272,13 +260,7 @@
         defaultDataSubId.value = subId
 
         val connection = getRepoForSubId(subId)
-        // This is always true here, because we split out disabled states at the data-source level
-        connection.dataEnabled.value = true
-        connection.networkName.value = NetworkNameModel.IntentDerived(CARRIER_MERGED_NAME)
-        connection.numberOfLevels.value = event.numberOfLevels
-        connection.cdmaRoaming.value = false
-        connection.connectionInfo.value = event.toMobileConnectionModel()
-        Log.e("CCS", "output connection info = ${connection.connectionInfo.value}")
+        connection.processCarrierMergedEvent(event)
     }
 
     private fun maybeRemoveSubscription(subId: Int?) {
@@ -332,29 +314,6 @@
     private fun subIdsString(): String =
         _subscriptions.value.joinToString(",") { it.subscriptionId.toString() }
 
-    private fun Mobile.toMobileConnectionModel(): MobileConnectionModel {
-        return MobileConnectionModel(
-            isEmergencyOnly = false, // TODO(b/261029387): not yet supported
-            isRoaming = roaming,
-            isInService = (level ?: 0) > 0,
-            isGsm = false, // TODO(b/261029387): not yet supported
-            cdmaLevel = level ?: 0,
-            primaryLevel = level ?: 0,
-            dataConnectionState =
-                DataConnectionState.Connected, // TODO(b/261029387): not yet supported
-            dataActivityDirection = (activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel(),
-            carrierNetworkChangeActive = carrierNetworkChange,
-            resolvedNetworkType = dataType.toResolvedNetworkType()
-        )
-    }
-
-    private fun FakeWifiEventModel.CarrierMerged.toMobileConnectionModel(): MobileConnectionModel {
-        return createCarrierMergedConnectionModel(
-            this.level,
-            activity.toMobileDataActivityModel(),
-        )
-    }
-
     private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
         val key = mobileMappingsReverseLookup.value[this] ?: "dis"
         return DefaultNetworkType(key)
@@ -364,8 +323,6 @@
         private const val TAG = "DemoMobileConnectionsRepo"
 
         private const val DEFAULT_SUB_ID = 1
-
-        private const val CARRIER_MERGED_NAME = "Carrier Merged Network"
     }
 }
 
@@ -374,18 +331,3 @@
     /** 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 {
-    override val connectionInfo = MutableStateFlow(MobileConnectionModel())
-
-    override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
-
-    override val dataEnabled = MutableStateFlow(true)
-
-    override val cdmaRoaming = MutableStateFlow(false)
-
-    override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
index 8f6a87b..94d6d0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -16,18 +16,17 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository.prod
 
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
 import android.telephony.TelephonyManager
 import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 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
 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.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
-import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import javax.inject.Inject
@@ -94,16 +93,6 @@
             }
         }
 
-    override val connectionInfo: StateFlow<MobileConnectionModel> =
-        combine(network, wifiRepository.wifiActivity) { network, activity ->
-                if (network == null) {
-                    MobileConnectionModel()
-                } else {
-                    createCarrierMergedConnectionModel(network.level, activity)
-                }
-            }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectionModel())
-
     override val cdmaRoaming: StateFlow<Boolean> = MutableStateFlow(ROAMING).asStateFlow()
 
     override val networkName: StateFlow<NetworkNameModel> =
@@ -129,34 +118,54 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
 
+    override val primaryLevel =
+        network
+            .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val cdmaLevel =
+        network
+            .map { it?.level ?: SIGNAL_STRENGTH_NONE_OR_UNKNOWN }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val dataActivityDirection = wifiRepository.wifiActivity
+
+    override val resolvedNetworkType =
+        network
+            .map {
+                if (it != null) {
+                    ResolvedNetworkType.CarrierMergedNetworkType
+                } else {
+                    ResolvedNetworkType.UnknownNetworkType
+                }
+            }
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                ResolvedNetworkType.UnknownNetworkType
+            )
+
+    override val dataConnectionState =
+        network
+            .map {
+                if (it != null) {
+                    DataConnectionState.Connected
+                } else {
+                    DataConnectionState.Disconnected
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), DataConnectionState.Disconnected)
+
+    override val isRoaming = MutableStateFlow(false).asStateFlow()
+    override val isEmergencyOnly = MutableStateFlow(false).asStateFlow()
+    override val operatorAlphaShort = MutableStateFlow(null).asStateFlow()
+    override val isInService = MutableStateFlow(true).asStateFlow()
+    override val isGsm = MutableStateFlow(false).asStateFlow()
+    override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow()
+
     override val dataEnabled: StateFlow<Boolean> = wifiRepository.isWifiEnabled
 
     companion object {
-        /**
-         * Creates an instance of [MobileConnectionModel] that represents a carrier merged network
-         * with the given [level] and [activity].
-         */
-        fun createCarrierMergedConnectionModel(
-            level: Int,
-            activity: DataActivityModel,
-        ): MobileConnectionModel {
-            return MobileConnectionModel(
-                primaryLevel = level,
-                cdmaLevel = level,
-                dataActivityDirection = activity,
-                // Here and below: These values are always the same for every carrier-merged
-                // connection.
-                resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
-                dataConnectionState = DataConnectionState.Connected,
-                isRoaming = ROAMING,
-                isEmergencyOnly = false,
-                operatorAlphaShort = null,
-                isInService = true,
-                isGsm = false,
-                carrierNetworkChangeActive = false,
-            )
-        }
-
         // Carrier merged is never roaming
         private const val ROAMING = false
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index a39ea0a..b3737ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -114,15 +114,147 @@
             .flatMapLatest { it.cdmaRoaming }
             .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaRoaming.value)
 
-    override val connectionInfo =
+    override val isEmergencyOnly =
         activeRepo
-            .flatMapLatest { it.connectionInfo }
+            .flatMapLatest { it.isEmergencyOnly }
             .logDiffsForTable(
                 tableLogBuffer,
                 columnPrefix = "",
-                initialValue = activeRepo.value.connectionInfo.value,
+                columnName = COL_EMERGENCY,
+                activeRepo.value.isEmergencyOnly.value
             )
-            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.connectionInfo.value)
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.isEmergencyOnly.value
+            )
+
+    override val isRoaming =
+        activeRepo
+            .flatMapLatest { it.isRoaming }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_ROAMING,
+                activeRepo.value.isRoaming.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value)
+
+    override val operatorAlphaShort =
+        activeRepo
+            .flatMapLatest { it.operatorAlphaShort }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_OPERATOR,
+                activeRepo.value.operatorAlphaShort.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.operatorAlphaShort.value
+            )
+
+    override val isInService =
+        activeRepo
+            .flatMapLatest { it.isInService }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_IN_SERVICE,
+                activeRepo.value.isInService.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value)
+
+    override val isGsm =
+        activeRepo
+            .flatMapLatest { it.isGsm }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_IS_GSM,
+                activeRepo.value.isGsm.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value)
+
+    override val cdmaLevel =
+        activeRepo
+            .flatMapLatest { it.cdmaLevel }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CDMA_LEVEL,
+                activeRepo.value.cdmaLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value)
+
+    override val primaryLevel =
+        activeRepo
+            .flatMapLatest { it.primaryLevel }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_PRIMARY_LEVEL,
+                activeRepo.value.primaryLevel.value
+            )
+            .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value)
+
+    override val dataConnectionState =
+        activeRepo
+            .flatMapLatest { it.dataConnectionState }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.dataConnectionState.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.dataConnectionState.value
+            )
+
+    override val dataActivityDirection =
+        activeRepo
+            .flatMapLatest { it.dataActivityDirection }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.dataActivityDirection.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.dataActivityDirection.value
+            )
+
+    override val carrierNetworkChangeActive =
+        activeRepo
+            .flatMapLatest { it.carrierNetworkChangeActive }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                columnName = COL_CARRIER_NETWORK_CHANGE,
+                activeRepo.value.carrierNetworkChangeActive.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.carrierNetworkChangeActive.value
+            )
+
+    override val resolvedNetworkType =
+        activeRepo
+            .flatMapLatest { it.resolvedNetworkType }
+            .logDiffsForTable(
+                tableLogBuffer,
+                columnPrefix = "",
+                activeRepo.value.resolvedNetworkType.value
+            )
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                activeRepo.value.resolvedNetworkType.value
+            )
 
     override val dataEnabled =
         activeRepo
@@ -187,4 +319,15 @@
             fun tableBufferLogName(subId: Int): String = "MobileConnectionLog[$subId]"
         }
     }
+
+    companion object {
+        const val COL_EMERGENCY = "emergencyOnly"
+        const val COL_ROAMING = "roaming"
+        const val COL_OPERATOR = "operatorName"
+        const val COL_IS_IN_SERVICE = "isInService"
+        const val COL_IS_GSM = "isGsm"
+        const val COL_CDMA_LEVEL = "cdmaLevel"
+        const val COL_PRIMARY_LEVEL = "primaryLevel"
+        const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive"
+    }
 }
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 e182bc6..f1fc386 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
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.IntentFilter
 import android.telephony.CellSignalStrength
+import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
 import android.telephony.CellSignalStrengthCdma
 import android.telephony.ServiceState
 import android.telephony.SignalStrength
@@ -37,7 +38,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
@@ -49,6 +50,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -62,10 +64,10 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.mapNotNull
-import kotlinx.coroutines.flow.scan
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
 
@@ -165,83 +167,100 @@
             }
             .shareIn(scope, SharingStarted.WhileSubscribed())
 
-    private fun updateConnectionState(
-        prevState: MobileConnectionModel,
-        callbackEvent: CallbackEvent,
-    ): MobileConnectionModel =
-        when (callbackEvent) {
-            is CallbackEvent.OnServiceStateChanged -> {
-                val serviceState = callbackEvent.serviceState
-                prevState.copy(
-                    isEmergencyOnly = serviceState.isEmergencyOnly,
-                    isRoaming = serviceState.roaming,
-                    operatorAlphaShort = serviceState.operatorAlphaShort,
-                    isInService = Utils.isInService(serviceState),
-                )
-            }
-            is CallbackEvent.OnSignalStrengthChanged -> {
-                val signalStrength = callbackEvent.signalStrength
-                val cdmaLevel =
-                    signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
-                        strengths ->
-                        if (!strengths.isEmpty()) {
-                            strengths[0].level
-                        } else {
-                            CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
-                        }
-                    }
-
-                val primaryLevel = signalStrength.level
-
-                prevState.copy(
-                    cdmaLevel = cdmaLevel,
-                    primaryLevel = primaryLevel,
-                    isGsm = signalStrength.isGsm,
-                )
-            }
-            is CallbackEvent.OnDataConnectionStateChanged -> {
-                prevState.copy(dataConnectionState = callbackEvent.dataState.toDataConnectionType())
-            }
-            is CallbackEvent.OnDataActivity -> {
-                prevState.copy(
-                    dataActivityDirection = callbackEvent.direction.toMobileDataActivityModel()
-                )
-            }
-            is CallbackEvent.OnCarrierNetworkChange -> {
-                prevState.copy(carrierNetworkChangeActive = callbackEvent.active)
-            }
-            is CallbackEvent.OnDisplayInfoChanged -> {
-                val telephonyDisplayInfo = callbackEvent.telephonyDisplayInfo
-                val networkType =
-                    if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
-                        UnknownNetworkType
-                    } else if (
-                        telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE
-                    ) {
-                        DefaultNetworkType(
-                            mobileMappingsProxy.toIconKey(telephonyDisplayInfo.networkType)
-                        )
-                    } else {
-                        OverrideNetworkType(
-                            mobileMappingsProxy.toIconKeyOverride(
-                                telephonyDisplayInfo.overrideNetworkType
-                            )
-                        )
-                    }
-                prevState.copy(resolvedNetworkType = networkType)
-            }
-            is CallbackEvent.OnDataEnabledChanged -> {
-                // Not part of this object, handled in a separate flow
-                prevState
-            }
-        }
-
-    override val connectionInfo = run {
-        val initial = MobileConnectionModel()
+    override val isEmergencyOnly =
         callbackEvents
-            .scan(initial, ::updateConnectionState)
-            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
-    }
+            .filterIsInstance<CallbackEvent.OnServiceStateChanged>()
+            .map { it.serviceState.isEmergencyOnly }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val isRoaming =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnServiceStateChanged>()
+            .map { it.serviceState.roaming }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val operatorAlphaShort =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnServiceStateChanged>()
+            .map { it.serviceState.operatorAlphaShort }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+
+    override val isInService =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnServiceStateChanged>()
+            .map { Utils.isInService(it.serviceState) }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val isGsm =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnSignalStrengthChanged>()
+            .map { it.signalStrength.isGsm }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val cdmaLevel =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnSignalStrengthChanged>()
+            .map {
+                it.signalStrength.getCellSignalStrengths(CellSignalStrengthCdma::class.java).let {
+                    strengths ->
+                    if (strengths.isNotEmpty()) {
+                        strengths[0].level
+                    } else {
+                        CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN
+                    }
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val primaryLevel =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnSignalStrengthChanged>()
+            .map { it.signalStrength.level }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
+
+    override val dataConnectionState =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnDataConnectionStateChanged>()
+            .map { it.dataState.toDataConnectionType() }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), Disconnected)
+
+    override val dataActivityDirection =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnDataActivity>()
+            .map { it.direction.toMobileDataActivityModel() }
+            .stateIn(
+                scope,
+                SharingStarted.WhileSubscribed(),
+                DataActivityModel(hasActivityIn = false, hasActivityOut = false)
+            )
+
+    override val carrierNetworkChangeActive =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnCarrierNetworkChange>()
+            .map { it.active }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+    override val resolvedNetworkType =
+        callbackEvents
+            .filterIsInstance<CallbackEvent.OnDisplayInfoChanged>()
+            .map {
+                if (it.telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
+                    UnknownNetworkType
+                } else if (
+                    it.telephonyDisplayInfo.overrideNetworkType == OVERRIDE_NETWORK_TYPE_NONE
+                ) {
+                    DefaultNetworkType(
+                        mobileMappingsProxy.toIconKey(it.telephonyDisplayInfo.networkType)
+                    )
+                } else {
+                    OverrideNetworkType(
+                        mobileMappingsProxy.toIconKeyOverride(
+                            it.telephonyDisplayInfo.overrideNetworkType
+                        )
+                    )
+                }
+            }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), UnknownNetworkType)
 
     override val numberOfLevels =
         systemUiCarrierConfig.shouldInflateSignalStrength
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 4caf2b0..7df6764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -34,6 +34,7 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
@@ -133,11 +134,9 @@
     override val isForceHidden: Flow<Boolean>,
     connectionRepository: MobileConnectionRepository,
 ) : MobileIconInteractor {
-    private val connectionInfo = connectionRepository.connectionInfo
-
     override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer
 
-    override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
+    override val activity = connectionRepository.dataActivityDirection
 
     override val isConnected: Flow<Boolean> = defaultMobileConnectivity.mapLatest { it.isConnected }
 
@@ -155,11 +154,11 @@
     override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled
 
     override val networkName =
-        combine(connectionInfo, connectionRepository.networkName) { connection, networkName ->
-                if (
-                    networkName is NetworkNameModel.Default && connection.operatorAlphaShort != null
-                ) {
-                    NetworkNameModel.IntentDerived(connection.operatorAlphaShort)
+        combine(connectionRepository.operatorAlphaShort, connectionRepository.networkName) {
+                operatorAlphaShort,
+                networkName ->
+                if (networkName is NetworkNameModel.Default && operatorAlphaShort != null) {
+                    NetworkNameModel.IntentDerived(operatorAlphaShort)
                 } else {
                     networkName
                 }
@@ -173,19 +172,19 @@
     /** Observable for the current RAT indicator icon ([MobileIconGroup]) */
     override val networkTypeIconGroup: StateFlow<MobileIconGroup> =
         combine(
-                connectionInfo,
+                connectionRepository.resolvedNetworkType,
                 defaultMobileIconMapping,
                 defaultMobileIconGroup,
                 isDefault,
-            ) { info, mapping, defaultGroup, isDefault ->
+            ) { resolvedNetworkType, mapping, defaultGroup, isDefault ->
                 if (!isDefault) {
                     return@combine NOT_DEFAULT_DATA
                 }
 
-                when (info.resolvedNetworkType) {
+                when (resolvedNetworkType) {
                     is ResolvedNetworkType.CarrierMergedNetworkType ->
-                        info.resolvedNetworkType.iconGroupOverride
-                    else -> mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
+                        resolvedNetworkType.iconGroupOverride
+                    else -> mapping[resolvedNetworkType.lookupKey] ?: defaultGroup
                 }
             }
             .distinctUntilChanged()
@@ -200,17 +199,19 @@
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
 
-    override val isEmergencyOnly: StateFlow<Boolean> =
-        connectionInfo
-            .mapLatest { it.isEmergencyOnly }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+    override val isEmergencyOnly = connectionRepository.isEmergencyOnly
 
     override val isRoaming: StateFlow<Boolean> =
-        combine(connectionInfo, connectionRepository.cdmaRoaming) { connection, cdmaRoaming ->
-                if (connection.carrierNetworkChangeActive) {
+        combine(
+                connectionRepository.carrierNetworkChangeActive,
+                connectionRepository.isGsm,
+                connectionRepository.isRoaming,
+                connectionRepository.cdmaRoaming,
+            ) { carrierNetworkChangeActive, isGsm, isRoaming, cdmaRoaming ->
+                if (carrierNetworkChangeActive) {
                     false
-                } else if (connection.isGsm) {
-                    connection.isRoaming
+                } else if (isGsm) {
+                    isRoaming
                 } else {
                     cdmaRoaming
                 }
@@ -218,12 +219,17 @@
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val level: StateFlow<Int> =
-        combine(connectionInfo, alwaysUseCdmaLevel) { connection, alwaysUseCdmaLevel ->
+        combine(
+                connectionRepository.isGsm,
+                connectionRepository.primaryLevel,
+                connectionRepository.cdmaLevel,
+                alwaysUseCdmaLevel,
+            ) { isGsm, primaryLevel, cdmaLevel, alwaysUseCdmaLevel ->
                 when {
                     // GSM connections should never use the CDMA level
-                    connection.isGsm -> connection.primaryLevel
-                    alwaysUseCdmaLevel -> connection.cdmaLevel
-                    else -> connection.primaryLevel
+                    isGsm -> primaryLevel
+                    alwaysUseCdmaLevel -> cdmaLevel
+                    else -> primaryLevel
                 }
             }
             .stateIn(scope, SharingStarted.WhileSubscribed(), 0)
@@ -236,12 +242,9 @@
         )
 
     override val isDataConnected: StateFlow<Boolean> =
-        connectionInfo
-            .mapLatest { connection -> connection.dataConnectionState == Connected }
+        connectionRepository.dataConnectionState
+            .map { it == Connected }
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
-    override val isInService =
-        connectionRepository.connectionInfo
-            .mapLatest { it.isInService }
-            .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+    override val isInService = connectionRepository.isInService
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 4dfa626..9ab7289 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -313,6 +313,25 @@
     }
 
     @Test
+    fun testOnLoadTwice_onlyChecksOnce() {
+        // When data is first loaded,
+        setUpMbsWithValidResolveInfo()
+        resumeListener.onMediaDataLoaded(KEY, null, data)
+
+        // We notify the manager to set a null action
+        verify(mediaDataManager).setResumeAction(KEY, null)
+
+        // If we then get another update from the app before the first check completes
+        assertThat(executor.numPending()).isEqualTo(1)
+        var dataWithCheck = data.copy(hasCheckedForResume = true)
+        resumeListener.onMediaDataLoaded(KEY, null, dataWithCheck)
+
+        // We do not try to start another check
+        assertThat(executor.numPending()).isEqualTo(1)
+        verify(mediaDataManager).setResumeAction(KEY, null)
+    }
+
+    @Test
     fun testOnUserUnlock_loadsTracks() {
         // Set up mock service to successfully find valid media
         val description = MediaDescription.Builder().setTitle(TITLE).build()
@@ -392,7 +411,7 @@
                 assertThat(result.size).isEqualTo(3)
                 assertThat(result[2].toLong()).isEqualTo(currentTime)
             }
-        verify(sharedPrefsEditor, times(1)).apply()
+        verify(sharedPrefsEditor).apply()
     }
 
     @Test
@@ -432,8 +451,8 @@
         resumeListener.userUnlockReceiver.onReceive(mockContext, intent)
 
         // We add its resume controls
-        verify(resumeBrowser, times(1)).findRecentMedia()
-        verify(mediaDataManager, times(1))
+        verify(resumeBrowser).findRecentMedia()
+        verify(mediaDataManager)
             .addResumptionControls(anyInt(), any(), any(), any(), any(), any(), eq(PACKAGE_NAME))
     }
 
@@ -516,7 +535,7 @@
                 assertThat(result.size).isEqualTo(3)
                 assertThat(result[2].toLong()).isEqualTo(currentTime)
             }
-        verify(sharedPrefsEditor, times(1)).apply()
+        verify(sharedPrefsEditor).apply()
     }
 
     @Test
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
deleted file mode 100644
index 45189cf..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileConnectionModelTest.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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_IN
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION_OUT
-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_IN,
-                    connection.dataActivityDirection.hasActivityIn.toString(),
-                )
-            )
-        assertThat(logger.changes)
-            .contains(
-                Pair(
-                    COL_ACTIVITY_DIRECTION_OUT,
-                    connection.dataActivityDirection.hasActivityOut.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/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
index 53cd71f1..44fbd5b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt
@@ -17,9 +17,11 @@
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
 import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
+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.Companion.DEFAULT_NUM_LEVELS
+import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import kotlinx.coroutines.flow.MutableStateFlow
 
 // TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
@@ -27,8 +29,19 @@
     override val subId: Int,
     override val tableLogBuffer: TableLogBuffer,
 ) : MobileConnectionRepository {
-    private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
-    override val connectionInfo = _connectionInfo
+    override val isEmergencyOnly = MutableStateFlow(false)
+    override val isRoaming = MutableStateFlow(false)
+    override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null)
+    override val isInService = MutableStateFlow(false)
+    override val isGsm = MutableStateFlow(false)
+    override val cdmaLevel = MutableStateFlow(0)
+    override val primaryLevel = MutableStateFlow(0)
+    override val dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
+    override val dataActivityDirection =
+        MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
+    override val carrierNetworkChangeActive = MutableStateFlow(false)
+    override val resolvedNetworkType: MutableStateFlow<ResolvedNetworkType> =
+        MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
 
     override val numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
 
@@ -40,10 +53,6 @@
     override val networkName =
         MutableStateFlow<NetworkNameModel>(NetworkNameModel.Default("default"))
 
-    fun setConnectionInfo(model: MobileConnectionModel) {
-        _connectionInfo.value = model
-    }
-
     fun setDataEnabled(enabled: Boolean) {
         _dataEnabled.value = enabled
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index b072dee..37fac34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.SysuiTestCase
 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.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
@@ -36,8 +35,11 @@
 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
@@ -123,34 +125,49 @@
             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 -> {
-                val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
                 assertThat(conn.subId).isEqualTo(model.subId)
-                assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.dataActivityDirection)
+                assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+                assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+                assertThat(conn.dataActivityDirection.value)
                     .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
-                assertThat(connectionInfo.carrierNetworkChangeActive)
+                assertThat(conn.carrierNetworkChangeActive.value)
                     .isEqualTo(model.carrierNetworkChange)
-                assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+                assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
                 assertThat(conn.networkName.value)
                     .isEqualTo(NetworkNameModel.IntentDerived(model.name))
 
                 // TODO(b/261029387): check these once we start handling them
-                assertThat(connectionInfo.isEmergencyOnly).isFalse()
-                assertThat(connectionInfo.isGsm).isFalse()
-                assertThat(connectionInfo.dataConnectionState)
-                    .isEqualTo(DataConnectionState.Connected)
+                assertThat(conn.isEmergencyOnly.value).isFalse()
+                assertThat(conn.isGsm.value).isFalse()
+                assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
             }
             // MobileDisabled isn't combinatorial in nature, and is tested in
             // DemoMobileConnectionsRepositoryTest.kt
             else -> {}
         }
+
+        job.cancel()
     }
 
     /** Matches [FakeNetworkEventModel] */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index f60d92b..0e45d8e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.dump.DumpManager
 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.MobileConnectionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
@@ -40,9 +39,11 @@
 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
@@ -524,47 +525,65 @@
             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
+        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 -> {
-                val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
                 assertThat(conn.subId).isEqualTo(model.subId)
-                assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-                assertThat(connectionInfo.dataActivityDirection)
+                assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+                assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+                assertThat(conn.dataActivityDirection.value)
                     .isEqualTo((model.activity ?: DATA_ACTIVITY_NONE).toMobileDataActivityModel())
-                assertThat(connectionInfo.carrierNetworkChangeActive)
+                assertThat(conn.carrierNetworkChangeActive.value)
                     .isEqualTo(model.carrierNetworkChange)
-                assertThat(connectionInfo.isRoaming).isEqualTo(model.roaming)
+                assertThat(conn.isRoaming.value).isEqualTo(model.roaming)
                 assertThat(conn.networkName.value)
                     .isEqualTo(NetworkNameModel.IntentDerived(model.name))
 
                 // TODO(b/261029387) check these once we start handling them
-                assertThat(connectionInfo.isEmergencyOnly).isFalse()
-                assertThat(connectionInfo.isGsm).isFalse()
-                assertThat(connectionInfo.dataConnectionState)
-                    .isEqualTo(DataConnectionState.Connected)
+                assertThat(conn.isEmergencyOnly.value).isFalse()
+                assertThat(conn.isGsm.value).isFalse()
+                assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
             }
             else -> {}
         }
+
+        job.cancel()
     }
 
-    private fun assertCarrierMergedConnection(
+    private fun TestScope.assertCarrierMergedConnection(
         conn: DemoMobileConnectionRepository,
         model: FakeWifiEventModel.CarrierMerged,
     ) {
-        val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
+        val job = startCollection(conn)
         assertThat(conn.subId).isEqualTo(model.subscriptionId)
-        assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
-        assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
-        assertThat(connectionInfo.carrierNetworkChangeActive).isEqualTo(false)
-        assertThat(connectionInfo.isRoaming).isEqualTo(false)
-        assertThat(connectionInfo.isEmergencyOnly).isFalse()
-        assertThat(connectionInfo.isGsm).isFalse()
-        assertThat(connectionInfo.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+        assertThat(conn.cdmaLevel.value).isEqualTo(model.level)
+        assertThat(conn.primaryLevel.value).isEqualTo(model.level)
+        assertThat(conn.carrierNetworkChangeActive.value).isEqualTo(false)
+        assertThat(conn.isRoaming.value).isEqualTo(false)
+        assertThat(conn.isEmergencyOnly.value).isFalse()
+        assertThat(conn.isGsm.value).isFalse()
+        assertThat(conn.dataConnectionState.value).isEqualTo(DataConnectionState.Connected)
+        job.cancel()
     }
 }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
index f0f213b..441186a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -22,7 +22,6 @@
 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
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -75,36 +74,48 @@
     }
 
     @Test
-    fun connectionInfo_inactiveWifi_isDefault() =
+    fun inactiveWifi_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestConnState: DataConnectionState? = null
+            var latestNetType: ResolvedNetworkType? = null
+
+            val dataJob =
+                underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+            val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            dataJob.cancel()
+            netJob.cancel()
         }
 
     @Test
-    fun connectionInfo_activeWifi_isDefault() =
+    fun activeWifi_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestConnState: DataConnectionState? = null
+            var latestNetType: ResolvedNetworkType? = null
+
+            val dataJob =
+                underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
+            val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            dataJob.cancel()
+            netJob.cancel()
         }
 
     @Test
-    fun connectionInfo_carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
+    fun carrierMergedWifi_isValidAndFieldsComeFromWifiNetwork() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setIsWifiEnabled(true)
             wifiRepository.setIsWifiDefault(true)
@@ -117,34 +128,16 @@
                 )
             )
 
-            val expected =
-                MobileConnectionModel(
-                    primaryLevel = 3,
-                    cdmaLevel = 3,
-                    dataConnectionState = DataConnectionState.Connected,
-                    dataActivityDirection =
-                        DataActivityModel(
-                            hasActivityIn = false,
-                            hasActivityOut = false,
-                        ),
-                    resolvedNetworkType = ResolvedNetworkType.CarrierMergedNetworkType,
-                    isRoaming = false,
-                    isEmergencyOnly = false,
-                    operatorAlphaShort = null,
-                    isInService = true,
-                    isGsm = false,
-                    carrierNetworkChangeActive = false,
-                )
-            assertThat(latest).isEqualTo(expected)
+            assertThat(latest).isEqualTo(3)
 
             job.cancel()
         }
 
     @Test
-    fun connectionInfo_activity_comesFromWifiActivity() =
+    fun activity_comesFromWifiActivity() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataActivityModel? = null
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setIsWifiEnabled(true)
             wifiRepository.setIsWifiDefault(true)
@@ -162,8 +155,8 @@
                 )
             )
 
-            assertThat(latest!!.dataActivityDirection.hasActivityIn).isTrue()
-            assertThat(latest!!.dataActivityDirection.hasActivityOut).isFalse()
+            assertThat(latest!!.hasActivityIn).isTrue()
+            assertThat(latest!!.hasActivityOut).isFalse()
 
             wifiRepository.setWifiActivity(
                 DataActivityModel(
@@ -172,17 +165,19 @@
                 )
             )
 
-            assertThat(latest!!.dataActivityDirection.hasActivityIn).isFalse()
-            assertThat(latest!!.dataActivityDirection.hasActivityOut).isTrue()
+            assertThat(latest!!.hasActivityIn).isFalse()
+            assertThat(latest!!.hasActivityOut).isTrue()
 
             job.cancel()
         }
 
     @Test
-    fun connectionInfo_carrierMergedWifi_wrongSubId_isDefault() =
+    fun carrierMergedWifi_wrongSubId_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestLevel: Int? = null
+            var latestType: ResolvedNetworkType? = null
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
+            val typeJob = underTest.resolvedNetworkType.onEach { latestType = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -192,20 +187,19 @@
                 )
             )
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
-            assertThat(latest!!.primaryLevel).isNotEqualTo(3)
-            assertThat(latest!!.resolvedNetworkType)
-                .isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
+            assertThat(latestLevel).isNotEqualTo(3)
+            assertThat(latestType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
 
-            job.cancel()
+            levelJob.cancel()
+            typeJob.cancel()
         }
 
     // This scenario likely isn't possible, but write a test for it anyway
     @Test
-    fun connectionInfo_carrierMergedButNotEnabled_isDefault() =
+    fun carrierMergedButNotEnabled_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -216,17 +210,17 @@
             )
             wifiRepository.setIsWifiEnabled(false)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latest).isNotEqualTo(3)
 
             job.cancel()
         }
 
     // This scenario likely isn't possible, but write a test for it anyway
     @Test
-    fun connectionInfo_carrierMergedButWifiNotDefault_isDefault() =
+    fun carrierMergedButWifiNotDefault_isDefault() =
         testScope.runTest {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
 
             wifiRepository.setWifiNetwork(
                 WifiNetworkModel.CarrierMerged(
@@ -237,7 +231,7 @@
             )
             wifiRepository.setIsWifiDefault(false)
 
-            assertThat(latest).isEqualTo(MobileConnectionModel())
+            assertThat(latest).isNotEqualTo(3)
 
             job.cancel()
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index cd4d847..db5a7d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -24,13 +24,12 @@
 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.MobileConnectionModel
-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_OPERATOR
-import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+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_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.MobileTelephonyHelpers.getTelephonyCallbackForType
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
@@ -94,16 +93,16 @@
     @Test
     fun startingIsCarrierMerged_usesCarrierMergedInitially() =
         testScope.runTest {
-            val carrierMergedConnectionInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                )
-            carrierMergedRepo.setConnectionInfo(carrierMergedConnectionInfo)
+            val carrierMergedOperatorName = "Carrier Merged Operator"
+            val nonCarrierMergedName = "Non-carrier-merged"
+
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+            mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
 
             initializeRepo(startingIsCarrierMerged = true)
 
             assertThat(underTest.activeRepo.value).isEqualTo(carrierMergedRepo)
-            assertThat(underTest.connectionInfo.value).isEqualTo(carrierMergedConnectionInfo)
+            assertThat(underTest.operatorAlphaShort.value).isEqualTo(carrierMergedOperatorName)
             verify(mobileFactory, never())
                 .build(
                     SUB_ID,
@@ -116,16 +115,16 @@
     @Test
     fun startingNotCarrierMerged_usesTypicalInitially() =
         testScope.runTest {
-            val mobileConnectionInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Operator",
-                )
-            mobileRepo.setConnectionInfo(mobileConnectionInfo)
+            val carrierMergedOperatorName = "Carrier Merged Operator"
+            val nonCarrierMergedName = "Typical Operator"
+
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperatorName
+            mobileRepo.operatorAlphaShort.value = nonCarrierMergedName
 
             initializeRepo(startingIsCarrierMerged = false)
 
             assertThat(underTest.activeRepo.value).isEqualTo(mobileRepo)
-            assertThat(underTest.connectionInfo.value).isEqualTo(mobileConnectionInfo)
+            assertThat(underTest.operatorAlphaShort.value).isEqualTo(nonCarrierMergedName)
             verify(carrierMergedFactory, never()).build(SUB_ID, tableLogBuffer)
         }
 
@@ -156,39 +155,40 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
+
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
             underTest.setIsCarrierMerged(true)
 
-            val info1 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                    primaryLevel = 1,
-                )
-            carrierMergedRepo.setConnectionInfo(info1)
+            val operator1 = "Carrier Merged Operator"
+            val level1 = 1
+            carrierMergedRepo.operatorAlphaShort.value = operator1
+            carrierMergedRepo.primaryLevel.value = level1
 
-            assertThat(latest).isEqualTo(info1)
+            assertThat(latestName).isEqualTo(operator1)
+            assertThat(latestLevel).isEqualTo(level1)
 
-            val info2 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator #2",
-                    primaryLevel = 2,
-                )
-            carrierMergedRepo.setConnectionInfo(info2)
+            val operator2 = "Carrier Merged Operator #2"
+            val level2 = 2
+            carrierMergedRepo.operatorAlphaShort.value = operator2
+            carrierMergedRepo.primaryLevel.value = level2
 
-            assertThat(latest).isEqualTo(info2)
+            assertThat(latestName).isEqualTo(operator2)
+            assertThat(latestLevel).isEqualTo(level2)
 
-            val info3 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator #3",
-                    primaryLevel = 3,
-                )
-            carrierMergedRepo.setConnectionInfo(info3)
+            val operator3 = "Carrier Merged Operator #3"
+            val level3 = 3
+            carrierMergedRepo.operatorAlphaShort.value = operator3
+            carrierMergedRepo.primaryLevel.value = level3
 
-            assertThat(latest).isEqualTo(info3)
+            assertThat(latestName).isEqualTo(operator3)
+            assertThat(latestLevel).isEqualTo(level3)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -196,39 +196,40 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
+
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
             underTest.setIsCarrierMerged(false)
 
-            val info1 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator",
-                    primaryLevel = 1,
-                )
-            mobileRepo.setConnectionInfo(info1)
+            val operator1 = "Typical Merged Operator"
+            val level1 = 1
+            mobileRepo.operatorAlphaShort.value = operator1
+            mobileRepo.primaryLevel.value = level1
 
-            assertThat(latest).isEqualTo(info1)
+            assertThat(latestName).isEqualTo(operator1)
+            assertThat(latestLevel).isEqualTo(level1)
 
-            val info2 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator #2",
-                    primaryLevel = 2,
-                )
-            mobileRepo.setConnectionInfo(info2)
+            val operator2 = "Typical Merged Operator #2"
+            val level2 = 2
+            mobileRepo.operatorAlphaShort.value = operator2
+            mobileRepo.primaryLevel.value = level2
 
-            assertThat(latest).isEqualTo(info2)
+            assertThat(latestName).isEqualTo(operator2)
+            assertThat(latestLevel).isEqualTo(level2)
 
-            val info3 =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Merged Operator #3",
-                    primaryLevel = 3,
-                )
-            mobileRepo.setConnectionInfo(info3)
+            val operator3 = "Typical Merged Operator #3"
+            val level3 = 3
+            mobileRepo.operatorAlphaShort.value = operator3
+            mobileRepo.primaryLevel.value = level3
 
-            assertThat(latest).isEqualTo(info3)
+            assertThat(latestName).isEqualTo(operator3)
+            assertThat(latestLevel).isEqualTo(level3)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -236,57 +237,58 @@
         testScope.runTest {
             initializeRepo(startingIsCarrierMerged = false)
 
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latestName: String? = null
+            var latestLevel: Int? = null
 
-            val carrierMergedInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Carrier Merged Operator",
-                    primaryLevel = 4,
-                )
-            carrierMergedRepo.setConnectionInfo(carrierMergedInfo)
+            val nameJob = underTest.operatorAlphaShort.onEach { latestName = it }.launchIn(this)
+            val levelJob = underTest.primaryLevel.onEach { latestLevel = it }.launchIn(this)
 
-            val mobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Typical Operator",
-                    primaryLevel = 2,
-                )
-            mobileRepo.setConnectionInfo(mobileInfo)
+            val carrierMergedOperator = "Carrier Merged Operator"
+            val carrierMergedLevel = 4
+            carrierMergedRepo.operatorAlphaShort.value = carrierMergedOperator
+            carrierMergedRepo.primaryLevel.value = carrierMergedLevel
+
+            val mobileName = "Typical Operator"
+            val mobileLevel = 2
+            mobileRepo.operatorAlphaShort.value = mobileName
+            mobileRepo.primaryLevel.value = mobileLevel
 
             // Start with the mobile info
-            assertThat(latest).isEqualTo(mobileInfo)
+            assertThat(latestName).isEqualTo(mobileName)
+            assertThat(latestLevel).isEqualTo(mobileLevel)
 
             // WHEN isCarrierMerged is set to true
             underTest.setIsCarrierMerged(true)
 
             // THEN the carrier merged info is used
-            assertThat(latest).isEqualTo(carrierMergedInfo)
+            assertThat(latestName).isEqualTo(carrierMergedOperator)
+            assertThat(latestLevel).isEqualTo(carrierMergedLevel)
 
-            val newCarrierMergedInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "New CM Operator",
-                    primaryLevel = 0,
-                )
-            carrierMergedRepo.setConnectionInfo(newCarrierMergedInfo)
+            val newCarrierMergedName = "New CM Operator"
+            val newCarrierMergedLevel = 0
+            carrierMergedRepo.operatorAlphaShort.value = newCarrierMergedName
+            carrierMergedRepo.primaryLevel.value = newCarrierMergedLevel
 
-            assertThat(latest).isEqualTo(newCarrierMergedInfo)
+            assertThat(latestName).isEqualTo(newCarrierMergedName)
+            assertThat(latestLevel).isEqualTo(newCarrierMergedLevel)
 
             // WHEN isCarrierMerged is set to false
             underTest.setIsCarrierMerged(false)
 
             // THEN the typical info is used
-            assertThat(latest).isEqualTo(mobileInfo)
+            assertThat(latestName).isEqualTo(mobileName)
+            assertThat(latestLevel).isEqualTo(mobileLevel)
 
-            val newMobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "New Mobile Operator",
-                    primaryLevel = 3,
-                )
-            mobileRepo.setConnectionInfo(newMobileInfo)
+            val newMobileName = "New MobileOperator"
+            val newMobileLevel = 3
+            mobileRepo.operatorAlphaShort.value = newMobileName
+            mobileRepo.primaryLevel.value = newMobileLevel
 
-            assertThat(latest).isEqualTo(newMobileInfo)
+            assertThat(latestName).isEqualTo(newMobileName)
+            assertThat(latestLevel).isEqualTo(newMobileLevel)
 
-            job.cancel()
+            nameJob.cancel()
+            levelJob.cancel()
         }
 
     @Test
@@ -370,7 +372,8 @@
 
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val emergencyJob = underTest.isEmergencyOnly.launchIn(this)
+            val operatorJob = underTest.operatorAlphaShort.launchIn(this)
 
             // WHEN we set up some mobile connection info
             val serviceState = ServiceState()
@@ -394,7 +397,8 @@
             assertThat(dumpBuffer()).contains("$COL_OPERATOR${BUFFER_SEPARATOR}OpDiff")
             assertThat(dumpBuffer()).contains("$COL_EMERGENCY${BUFFER_SEPARATOR}true")
 
-            job.cancel()
+            emergencyJob.cancel()
+            operatorJob.cancel()
         }
 
     @Test
@@ -409,7 +413,7 @@
 
             initializeRepo(startingIsCarrierMerged = true)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             // WHEN we set up carrier merged info
             val networkId = 2
@@ -452,7 +456,7 @@
 
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             // WHEN we set up some mobile connection info
             val signalStrength = mock<SignalStrength>()
@@ -502,12 +506,7 @@
             assertThat(bufferAfterCarrierMerged).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
 
             // WHEN the normal network is updated
-            val newMobileInfo =
-                MobileConnectionModel(
-                    operatorAlphaShort = "Mobile Operator 2",
-                    primaryLevel = 0,
-                )
-            mobileRepo.setConnectionInfo(newMobileInfo)
+            mobileRepo.primaryLevel.value = 0
 
             // THEN the new level is logged
             assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}0")
@@ -529,7 +528,7 @@
             // WHEN isCarrierMerged = false
             initializeRepo(startingIsCarrierMerged = false)
 
-            val job = underTest.connectionInfo.launchIn(this)
+            val job = underTest.primaryLevel.launchIn(this)
 
             val signalStrength = mock<SignalStrength>()
             whenever(signalStrength.level).thenReturn(1)
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 bd5a4d7..f6e5959 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,13 +50,15 @@
 import android.telephony.TelephonyManager.EXTRA_SPN
 import android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID
 import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
+import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
 import androidx.test.filters.SmallTest
+import com.android.settingslib.mobile.MobileMappings
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 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
+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.ResolvedNetworkType.OverrideNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
@@ -135,235 +137,285 @@
     }
 
     @Test
-    fun testFlowForSubId_default() =
+    fun emergencyOnly() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
-
-            assertThat(latest).isEqualTo(MobileConnectionModel())
-
-            job.cancel()
-        }
-
-    @Test
-    fun testFlowForSubId_emergencyOnly() =
-        runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Boolean? = null
+            val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
 
             val serviceState = ServiceState()
             serviceState.isEmergencyOnly = true
 
             getTelephonyCallbackForType<ServiceStateListener>().onServiceStateChanged(serviceState)
 
-            assertThat(latest?.isEmergencyOnly).isEqualTo(true)
+            assertThat(latest).isEqualTo(true)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_emergencyOnly_toggles() =
+    fun emergencyOnly_toggles() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Boolean? = null
+            val job = underTest.isEmergencyOnly.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<ServiceStateListener>()
             val serviceState = ServiceState()
             serviceState.isEmergencyOnly = true
             callback.onServiceStateChanged(serviceState)
+            assertThat(latest).isTrue()
+
             serviceState.isEmergencyOnly = false
             callback.onServiceStateChanged(serviceState)
 
-            assertThat(latest?.isEmergencyOnly).isEqualTo(false)
+            assertThat(latest).isFalse()
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_signalStrengths_levelsUpdate() =
+    fun cdmaLevelUpdates() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.cdmaLevel.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
-            val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
             callback.onSignalStrengthsChanged(strength)
 
-            assertThat(latest?.isGsm).isEqualTo(true)
-            assertThat(latest?.primaryLevel).isEqualTo(1)
-            assertThat(latest?.cdmaLevel).isEqualTo(2)
+            assertThat(latest).isEqualTo(2)
+
+            // gsmLevel updates, no change to cdmaLevel
+            strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
+
+            assertThat(latest).isEqualTo(2)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_connected() =
+    fun gsmLevelUpdates() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Int? = null
+            val job = underTest.primaryLevel.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isEqualTo(1)
+
+            strength = signalStrength(gsmLevel = 3, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isEqualTo(3)
+
+            job.cancel()
+        }
+
+    @Test
+    fun isGsm() =
+        runBlocking(IMMEDIATE) {
+            var latest: Boolean? = null
+            val job = underTest.isGsm.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
+            var strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isTrue()
+
+            strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = false)
+            callback.onSignalStrengthsChanged(strength)
+
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
+    fun dataConnectionState_connected() =
+        runBlocking(IMMEDIATE) {
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_CONNECTED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connected)
+            assertThat(latest).isEqualTo(DataConnectionState.Connected)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_connecting() =
+    fun dataConnectionState_connecting() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_CONNECTING, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Connecting)
+            assertThat(latest).isEqualTo(DataConnectionState.Connecting)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_disconnected() =
+    fun dataConnectionState_disconnected() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_DISCONNECTED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnected)
+            assertThat(latest).isEqualTo(DataConnectionState.Disconnected)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_disconnecting() =
+    fun dataConnectionState_disconnecting() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_DISCONNECTING, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Disconnecting)
+            assertThat(latest).isEqualTo(DataConnectionState.Disconnecting)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_suspended() =
+    fun dataConnectionState_suspended() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_SUSPENDED, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Suspended)
+            assertThat(latest).isEqualTo(DataConnectionState.Suspended)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_handoverInProgress() =
+    fun dataConnectionState_handoverInProgress() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_HANDOVER_IN_PROGRESS, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState)
-                .isEqualTo(DataConnectionState.HandoverInProgress)
+            assertThat(latest).isEqualTo(DataConnectionState.HandoverInProgress)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_unknown() =
+    fun dataConnectionState_unknown() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(DATA_UNKNOWN, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Unknown)
+            assertThat(latest).isEqualTo(DataConnectionState.Unknown)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataConnectionState_invalid() =
+    fun dataConnectionState_invalid() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataConnectionState? = null
+            val job = underTest.dataConnectionState.onEach { latest = it }.launchIn(this)
 
             val callback =
                 getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
             callback.onDataConnectionStateChanged(45, 200 /* unused */)
 
-            assertThat(latest?.dataConnectionState).isEqualTo(DataConnectionState.Invalid)
+            assertThat(latest).isEqualTo(DataConnectionState.Invalid)
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_dataActivity() =
+    fun dataActivity() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: DataActivityModel? = null
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<DataActivityListener>()
             callback.onDataActivity(DATA_ACTIVITY_INOUT)
 
-            assertThat(latest?.dataActivityDirection)
-                .isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
+            assertThat(latest).isEqualTo(DATA_ACTIVITY_INOUT.toMobileDataActivityModel())
 
             job.cancel()
         }
 
     @Test
-    fun testFlowForSubId_carrierNetworkChange() =
+    fun carrierNetworkChange() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: Boolean? = null
+            val job = underTest.carrierNetworkChangeActive.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.CarrierNetworkListener>()
             callback.onCarrierNetworkChange(true)
 
-            assertThat(latest?.carrierNetworkChangeActive).isEqualTo(true)
+            assertThat(latest).isEqualTo(true)
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_default() =
+    fun networkType_default() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val expected = UnknownNetworkType
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_updatesUsingDefault() =
+    fun networkType_unknown_hasCorrectKey() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
+
+            val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
+            val type = NETWORK_TYPE_UNKNOWN
+            val expected = UnknownNetworkType
+            val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
+            callback.onDisplayInfoChanged(ti)
+
+            assertThat(latest).isEqualTo(expected)
+            assertThat(latest!!.lookupKey).isEqualTo(MobileMappings.toIconKey(type))
+
+            job.cancel()
+        }
+
+    @Test
+    fun networkType_updatesUsingDefault() =
+        runBlocking(IMMEDIATE) {
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
             val type = NETWORK_TYPE_LTE
@@ -371,16 +423,16 @@
             val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
             callback.onDisplayInfoChanged(ti)
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
 
             job.cancel()
         }
 
     @Test
-    fun subscriptionFlow_networkType_updatesUsingOverride() =
+    fun networkType_updatesUsingOverride() =
         runBlocking(IMMEDIATE) {
-            var latest: MobileConnectionModel? = null
-            val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
+            var latest: ResolvedNetworkType? = null
+            val job = underTest.resolvedNetworkType.onEach { latest = it }.launchIn(this)
 
             val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
             val type = OVERRIDE_NETWORK_TYPE_LTE_CA
@@ -392,7 +444,7 @@
                 }
             callback.onDisplayInfoChanged(ti)
 
-            assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
+            assertThat(latest).isEqualTo(expected)
 
             job.cancel()
         }
@@ -466,7 +518,7 @@
     fun `roaming - gsm - queries service state`() =
         runBlocking(IMMEDIATE) {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isRoaming }.launchIn(this)
+            val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             val serviceState = ServiceState()
             serviceState.roaming = false
@@ -492,8 +544,7 @@
     fun `activity - updates from callback`() =
         runBlocking(IMMEDIATE) {
             var latest: DataActivityModel? = null
-            val job =
-                underTest.connectionInfo.onEach { latest = it.dataActivityDirection }.launchIn(this)
+            val job = underTest.dataActivityDirection.onEach { latest = it }.launchIn(this)
 
             assertThat(latest)
                 .isEqualTo(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
@@ -611,8 +662,7 @@
         runBlocking(IMMEDIATE) {
             var latest: String? = null
 
-            val job =
-                underTest.connectionInfo.onEach { latest = it.operatorAlphaShort }.launchIn(this)
+            val job = underTest.operatorAlphaShort.onEach { latest = it }.launchIn(this)
 
             val shortName = "short name"
             val serviceState = ServiceState()
@@ -633,7 +683,7 @@
     fun `connection model - isInService - not iwlan`() =
         runBlocking(IMMEDIATE) {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
+            val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
             val serviceState = ServiceState()
             serviceState.voiceRegState = STATE_IN_SERVICE
@@ -658,7 +708,7 @@
     fun `connection model - isInService - is iwlan - voice out of service - data in service`() =
         runBlocking(IMMEDIATE) {
             var latest: Boolean? = null
-            val job = underTest.connectionInfo.onEach { latest = it.isInService }.launchIn(this)
+            val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
             // Mock the service state here so we can make it specifically IWLAN
             val serviceState: ServiceState = mock()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index fa072fc..1eb1056 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -23,7 +23,6 @@
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.SysuiTestCase
 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
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -74,9 +73,7 @@
     @Test
     fun gsm_level_default_unknown() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(isGsm = true),
-            )
+            connectionRepository.isGsm.value = true
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -89,13 +86,9 @@
     @Test
     fun gsm_usesGsmLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL
-                ),
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -108,13 +101,9 @@
     @Test
     fun gsm_alwaysShowCdmaTrue_stillUsesGsmLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL,
-                ),
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
 
             var latest: Int? = null
@@ -128,9 +117,7 @@
     @Test
     fun notGsm_level_default_unknown() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(isGsm = false),
-            )
+            connectionRepository.isGsm.value = false
 
             var latest: Int? = null
             val job = underTest.level.onEach { latest = it }.launchIn(this)
@@ -142,13 +129,9 @@
     @Test
     fun notGsm_alwaysShowCdmaTrue_usesCdmaLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL
-                ),
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = true
 
             var latest: Int? = null
@@ -162,13 +145,9 @@
     @Test
     fun notGsm_alwaysShowCdmaFalse_usesPrimaryLevel() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    primaryLevel = GSM_LEVEL,
-                    cdmaLevel = CDMA_LEVEL,
-                ),
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.primaryLevel.value = GSM_LEVEL
+            connectionRepository.cdmaLevel.value = CDMA_LEVEL
             mobileIconsInteractor.alwaysUseCdmaLevel.value = false
 
             var latest: Int? = null
@@ -197,11 +176,8 @@
     @Test
     fun iconGroup_three_g() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -214,23 +190,14 @@
     @Test
     fun iconGroup_updates_on_change() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        DefaultNetworkType(
-                            mobileMappingsProxy.toIconKey(FOUR_G),
-                        ),
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(FOUR_G))
             yield()
 
             assertThat(latest).isEqualTo(TelephonyIcons.FOUR_G)
@@ -241,12 +208,8 @@
     @Test
     fun iconGroup_5g_override_type() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                OverrideNetworkType(mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -259,12 +222,8 @@
     @Test
     fun iconGroup_default_if_no_lookup() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType =
-                        DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)),
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -277,11 +236,7 @@
     @Test
     fun iconGroup_carrierMerged_usesOverride() =
         runBlocking(IMMEDIATE) {
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = CarrierMergedNetworkType,
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value = CarrierMergedNetworkType
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -295,11 +250,8 @@
     fun `icon group - checks default data`() =
         runBlocking(IMMEDIATE) {
             mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
-                ),
-            )
+            connectionRepository.resolvedNetworkType.value =
+                DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
 
             var latest: MobileIconGroup? = null
             val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
@@ -380,9 +332,7 @@
             var latest: Boolean? = null
             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(dataConnectionState = DataConnectionState.Connected)
-            )
+            connectionRepository.dataConnectionState.value = DataConnectionState.Connected
             yield()
 
             assertThat(latest).isTrue()
@@ -396,9 +346,7 @@
             var latest: Boolean? = null
             val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(dataConnectionState = DataConnectionState.Disconnected)
-            )
+            connectionRepository.dataConnectionState.value = DataConnectionState.Disconnected
 
             assertThat(latest).isFalse()
 
@@ -411,11 +359,11 @@
             var latest: Boolean? = null
             val job = underTest.isInService.onEach { latest = it }.launchIn(this)
 
-            connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = true))
+            connectionRepository.isInService.value = true
 
             assertThat(latest).isTrue()
 
-            connectionRepository.setConnectionInfo(MobileConnectionModel(isInService = false))
+            connectionRepository.isInService.value = false
 
             assertThat(latest).isFalse()
 
@@ -429,22 +377,13 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = false,
-                )
-            )
+            connectionRepository.isGsm.value = true
+            connectionRepository.isRoaming.value = false
             yield()
 
             assertThat(latest).isFalse()
 
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = true,
-                )
-            )
+            connectionRepository.isRoaming.value = true
             yield()
 
             assertThat(latest).isTrue()
@@ -459,23 +398,15 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = false
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = true,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = true
             yield()
 
             assertThat(latest).isFalse()
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = false,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = false
             yield()
 
             assertThat(latest).isTrue()
@@ -490,25 +421,15 @@
             val job = underTest.isRoaming.onEach { latest = it }.launchIn(this)
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = false,
-                    isRoaming = true,
-                    carrierNetworkChangeActive = true,
-                )
-            )
+            connectionRepository.isGsm.value = false
+            connectionRepository.isRoaming.value = true
+            connectionRepository.carrierNetworkChangeActive.value = true
             yield()
 
             assertThat(latest).isFalse()
 
             connectionRepository.cdmaRoaming.value = true
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(
-                    isGsm = true,
-                    isRoaming = true,
-                    carrierNetworkChangeActive = true,
-                )
-            )
+            connectionRepository.isGsm.value = true
             yield()
 
             assertThat(latest).isFalse()
@@ -526,24 +447,20 @@
 
             // Default network name, operator name is non-null, uses the operator name
             connectionRepository.networkName.value = DEFAULT_NAME
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(operatorAlphaShort = testOperatorName)
-            )
+            connectionRepository.operatorAlphaShort.value = testOperatorName
             yield()
 
             assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived(testOperatorName))
 
             // Default network name, operator name is null, uses the default
-            connectionRepository.setConnectionInfo(MobileConnectionModel(operatorAlphaShort = null))
+            connectionRepository.operatorAlphaShort.value = null
             yield()
 
             assertThat(latest).isEqualTo(DEFAULT_NAME)
 
             // Derived network name, operator name non-null, uses the derived name
             connectionRepository.networkName.value = DERIVED_NAME
-            connectionRepository.setConnectionInfo(
-                MobileConnectionModel(operatorAlphaShort = testOperatorName)
-            )
+            connectionRepository.operatorAlphaShort.value = testOperatorName
             yield()
 
             assertThat(latest).isEqualTo(DERIVED_NAME)
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5ecc7f2..c869fcd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -873,10 +873,6 @@
                 mAutomaticBrightnessController.stop();
             }
 
-            if (mScreenOffBrightnessSensorController != null) {
-                mScreenOffBrightnessSensorController.stop();
-            }
-
             if (mBrightnessSetting != null) {
                 mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
             }
@@ -1125,6 +1121,7 @@
 
             if (mScreenOffBrightnessSensorController != null) {
                 mScreenOffBrightnessSensorController.stop();
+                mScreenOffBrightnessSensorController = null;
             }
             loadScreenOffBrightnessSensor();
             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1242,6 +1239,10 @@
             mPowerState.stop();
             mPowerState = null;
         }
+
+        if (mScreenOffBrightnessSensorController != null) {
+            mScreenOffBrightnessSensorController.stop();
+        }
     }
 
     private void updatePowerState() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index cf90e14..de5defa 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -8105,9 +8105,9 @@
         if (isFixedOrientationLetterboxAllowed) {
             resolveFixedOrientationConfiguration(newParentConfiguration);
         }
-
-        if (getCompatDisplayInsets() != null) {
-            resolveSizeCompatModeConfiguration(newParentConfiguration);
+        final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
+        if (compatDisplayInsets != null) {
+            resolveSizeCompatModeConfiguration(newParentConfiguration, compatDisplayInsets);
         } else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
             // We ignore activities' requested orientation in multi-window modes. They may be
             // taken into consideration in resolveFixedOrientationConfiguration call above.
@@ -8124,7 +8124,7 @@
             resolveAspectRatioRestriction(newParentConfiguration);
         }
 
-        if (isFixedOrientationLetterboxAllowed || getCompatDisplayInsets() != null
+        if (isFixedOrientationLetterboxAllowed || compatDisplayInsets != null
                 // In fullscreen, can be letterboxed for aspect ratio.
                 || !inMultiWindowMode()) {
             updateResolvedBoundsPosition(newParentConfiguration);
@@ -8132,7 +8132,7 @@
 
         boolean isIgnoreOrientationRequest = mDisplayContent != null
                 && mDisplayContent.getIgnoreOrientationRequest();
-        if (getCompatDisplayInsets() == null
+        if (compatDisplayInsets == null
                 // for size compat mode set in updateCompatDisplayInsets
                 // Fixed orientation letterboxing is possible on both large screen devices
                 // with ignoreOrientationRequest enabled and on phones in split screen even with
@@ -8179,7 +8179,7 @@
                         info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
                         info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
                         !matchParentBounds(),
-                        getCompatDisplayInsets() != null,
+                        compatDisplayInsets != null,
                         shouldCreateCompatDisplayInsets());
             }
             resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8587,7 +8587,8 @@
      * Resolves consistent screen configuration for orientation and rotation changes without
      * inheriting the parent bounds.
      */
-    private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
+    private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration,
+            @NonNull CompatDisplayInsets compatDisplayInsets) {
         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
 
@@ -8608,13 +8609,13 @@
                 ? requestedOrientation
                 // We should use the original orientation of the activity when possible to avoid
                 // forcing the activity in the opposite orientation.
-                : getCompatDisplayInsets().mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
-                        ? getCompatDisplayInsets().mOriginalRequestedOrientation
+                : compatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+                        ? compatDisplayInsets.mOriginalRequestedOrientation
                         : newParentConfiguration.orientation;
         int rotation = newParentConfiguration.windowConfiguration.getRotation();
         final boolean isFixedToUserRotation = mDisplayContent == null
                 || mDisplayContent.getDisplayRotation().isFixedToUserRotation();
-        if (!isFixedToUserRotation && !getCompatDisplayInsets().mIsFloating) {
+        if (!isFixedToUserRotation && !compatDisplayInsets.mIsFloating) {
             // Use parent rotation because the original display can be rotated.
             resolvedConfig.windowConfiguration.setRotation(rotation);
         } else {
@@ -8630,11 +8631,11 @@
         // rely on them to contain the original and unchanging width and height of the app.
         final Rect containingAppBounds = new Rect();
         final Rect containingBounds = mTmpBounds;
-        getCompatDisplayInsets().getContainerBounds(containingAppBounds, containingBounds, rotation,
+        compatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
                 orientation, orientationRequested, isFixedToUserRotation);
         resolvedBounds.set(containingBounds);
         // The size of floating task is fixed (only swap), so the aspect ratio is already correct.
-        if (!getCompatDisplayInsets().mIsFloating) {
+        if (!compatDisplayInsets.mIsFloating) {
             mIsAspectRatioApplied =
                     applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
         }
@@ -8643,7 +8644,7 @@
         // are calculated in compat container space. The actual position on screen will be applied
         // later, so the calculation is simpler that doesn't need to involve offset from parent.
         getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
-                getCompatDisplayInsets());
+                compatDisplayInsets);
         // Use current screen layout as source because the size of app is independent to parent.
         resolvedConfig.screenLayout = TaskFragment.computeScreenLayoutOverride(
                 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index c20a513..d9f2b6e 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1433,7 +1433,7 @@
      * the first opaque activity beneath.
      */
     boolean hasInheritedLetterboxBehavior() {
-        return mLetterboxConfigListener != null && !mActivityRecord.matchParentBounds();
+        return mLetterboxConfigListener != null;
     }
 
     /**