diff --git a/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml b/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml
new file mode 100644
index 0000000000000..952f056b30239
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/shade_carrier_new.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 8485fe2c6526f..f0bd4f0f282ff 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -398,6 +398,10 @@ object Flags {
// TODO(b/294588085): Tracking Bug
val WIFI_SECONDARY_NETWORKS = releasedFlag("wifi_secondary_networks")
+ // TODO(b/290676905): Tracking Bug
+ val NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS =
+ unreleasedFlag("new_shade_carrier_group_mobile_icons")
+
// 700 - dialer/calls
// TODO(b/254512734): Tracking Bug
val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag("ongoing_call_status_bar_chip")
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrier.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrier.java
index 8586828af0cdd..8612cdf12c6e4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrier.java
@@ -34,6 +34,7 @@ import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView;
import com.android.systemui.util.LargeScreenUtils;
import java.util.Objects;
@@ -44,6 +45,7 @@ public class ShadeCarrier extends LinearLayout {
private TextView mCarrierText;
private ImageView mMobileSignal;
private ImageView mMobileRoaming;
+ private ModernShadeCarrierGroupMobileView mModernMobileView;
private View mSpacer;
@Nullable
private CellSignalState mLastSignalState;
@@ -77,6 +79,23 @@ public class ShadeCarrier extends LinearLayout {
updateResources();
}
+ /** Removes a ModernStatusBarMobileView from the ViewGroup. */
+ public void removeModernMobileView() {
+ if (mModernMobileView != null) {
+ removeView(mModernMobileView);
+ mModernMobileView = null;
+ }
+ }
+
+ /** Adds a ModernStatusBarMobileView to the ViewGroup. */
+ public void addModernMobileView(ModernShadeCarrierGroupMobileView mobileView) {
+ mModernMobileView = mobileView;
+ mMobileGroup.setVisibility(View.GONE);
+ mSpacer.setVisibility(View.GONE);
+ mCarrierText.setVisibility(View.GONE);
+ addView(mobileView);
+ }
+
/**
* Update the state of this view
* @param state the current state of the signal for this view
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index ad49b267c6ac9..98d8a53b83c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -16,6 +16,7 @@
package com.android.systemui.shade.carrier;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
import android.annotation.MainThread;
@@ -46,8 +47,17 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.SignalCallback;
+import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
+import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
+import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
+import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView;
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel;
import com.android.systemui.util.CarrierConfigTracker;
+import java.util.List;
import java.util.function.Consumer;
import javax.inject.Inject;
@@ -62,12 +72,16 @@ public class ShadeCarrierGroupController {
private final ActivityStarter mActivityStarter;
private final Handler mBgHandler;
+ private final Context mContext;
private final NetworkController mNetworkController;
private final CarrierTextManager mCarrierTextManager;
private final TextView mNoSimTextView;
// Non final for testing
private H mMainHandler;
private final Callback mCallback;
+ private final MobileIconsViewModel mMobileIconsViewModel;
+ private final MobileContextProvider mMobileContextProvider;
+ private final StatusBarPipelineFlags mStatusBarPipelineFlags;
private boolean mListening;
private final CellSignalState[] mInfos =
new CellSignalState[SIM_SLOTS];
@@ -91,7 +105,7 @@ public class ShadeCarrierGroupController {
Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex);
return;
}
- if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (slotIndex == INVALID_SIM_SLOT_INDEX) {
Log.e(TAG, "Invalid SIM slot index for subscription: " + indicators.subId);
return;
}
@@ -129,15 +143,25 @@ public class ShadeCarrierGroupController {
}
}
- private ShadeCarrierGroupController(ShadeCarrierGroup view, ActivityStarter activityStarter,
- @Background Handler bgHandler, @Main Looper mainLooper,
+ private ShadeCarrierGroupController(
+ ShadeCarrierGroup view,
+ ActivityStarter activityStarter,
+ @Background Handler bgHandler,
+ @Main Looper mainLooper,
NetworkController networkController,
- CarrierTextManager.Builder carrierTextManagerBuilder, Context context,
- CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) {
-
+ CarrierTextManager.Builder carrierTextManagerBuilder,
+ Context context,
+ CarrierConfigTracker carrierConfigTracker,
+ SlotIndexResolver slotIndexResolver,
+ MobileUiAdapter mobileUiAdapter,
+ MobileContextProvider mobileContextProvider,
+ StatusBarPipelineFlags statusBarPipelineFlags
+ ) {
+ mContext = context;
mActivityStarter = activityStarter;
mBgHandler = bgHandler;
mNetworkController = networkController;
+ mStatusBarPipelineFlags = statusBarPipelineFlags;
mCarrierTextManager = carrierTextManagerBuilder
.setShowAirplaneMode(false)
.setShowMissingSim(false)
@@ -162,6 +186,14 @@ public class ShadeCarrierGroupController {
mCarrierGroups[1] = view.getCarrier2View();
mCarrierGroups[2] = view.getCarrier3View();
+ mMobileContextProvider = mobileContextProvider;
+ mMobileIconsViewModel = mobileUiAdapter.getMobileIconsViewModel();
+
+ if (mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
+ mobileUiAdapter.setShadeCarrierGroupController(this);
+ MobileIconsBinder.bind(view, mMobileIconsViewModel);
+ }
+
mCarrierDividers[0] = view.getCarrierDivider1();
mCarrierDividers[1] = view.getCarrierDivider2();
@@ -193,6 +225,50 @@ public class ShadeCarrierGroupController {
});
}
+ /** Updates the number of visible mobile icons using the new pipeline. */
+ public void updateModernMobileIcons(List subIds) {
+ if (!mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
+ Log.d(TAG, "ignoring new pipeline callback because new mobile icon is disabled");
+ return;
+ }
+
+ for (ShadeCarrier carrier : mCarrierGroups) {
+ carrier.removeModernMobileView();
+ }
+
+ List iconDataList = processSubIdList(subIds);
+
+ for (IconData iconData : iconDataList) {
+ ShadeCarrier carrier = mCarrierGroups[iconData.slotIndex];
+
+ Context mobileContext =
+ mMobileContextProvider.getMobileContextForSub(iconData.subId, mContext);
+ ModernShadeCarrierGroupMobileView modernMobileView = ModernShadeCarrierGroupMobileView
+ .constructAndBind(
+ mobileContext,
+ mMobileIconsViewModel.getLogger(),
+ "mobile_carrier_shade_group",
+ (ShadeCarrierGroupMobileIconViewModel) mMobileIconsViewModel
+ .viewModelForSub(iconData.subId,
+ StatusBarLocation.SHADE_CARRIER_GROUP)
+ );
+ carrier.addModernMobileView(modernMobileView);
+ }
+ }
+
+ @VisibleForTesting
+ List processSubIdList(List subIds) {
+ return subIds
+ .stream()
+ .limit(SIM_SLOTS)
+ .map(subId -> new IconData(subId, getSlotIndex(subId)))
+ .filter(iconData ->
+ iconData.slotIndex < SIM_SLOTS
+ && iconData.slotIndex != INVALID_SIM_SLOT_INDEX
+ )
+ .toList();
+ }
+
@VisibleForTesting
protected int getSlotIndex(int subscriptionId) {
return mSlotIndexResolver.getSlotIndex(subscriptionId);
@@ -269,8 +345,12 @@ public class ShadeCarrierGroupController {
}
}
- for (int i = 0; i < SIM_SLOTS; i++) {
- mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
+ if (mStatusBarPipelineFlags.useNewShadeCarrierGroupMobileIcons()) {
+ Log.d(TAG, "ignoring old pipeline callback because new mobile icon is enabled");
+ } else {
+ for (int i = 0; i < SIM_SLOTS; i++) {
+ mCarrierGroups[i].updateState(mInfos[i], singleCarrier);
+ }
}
mCarrierDividers[0].setVisibility(
@@ -306,7 +386,7 @@ public class ShadeCarrierGroupController {
Log.w(TAG, "updateInfoCarrier - slot: " + slot);
continue;
}
- if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ if (slot == INVALID_SIM_SLOT_INDEX) {
Log.e(TAG,
"Invalid SIM slot index for subscription: "
+ info.subscriptionIds[i]);
@@ -385,12 +465,24 @@ public class ShadeCarrierGroupController {
private final Context mContext;
private final CarrierConfigTracker mCarrierConfigTracker;
private final SlotIndexResolver mSlotIndexResolver;
+ private final MobileUiAdapter mMobileUiAdapter;
+ private final MobileContextProvider mMobileContextProvider;
+ private final StatusBarPipelineFlags mStatusBarPipelineFlags;
@Inject
- public Builder(ActivityStarter activityStarter, @Background Handler handler,
- @Main Looper looper, NetworkController networkController,
- CarrierTextManager.Builder carrierTextControllerBuilder, Context context,
- CarrierConfigTracker carrierConfigTracker, SlotIndexResolver slotIndexResolver) {
+ public Builder(
+ ActivityStarter activityStarter,
+ @Background Handler handler,
+ @Main Looper looper,
+ NetworkController networkController,
+ CarrierTextManager.Builder carrierTextControllerBuilder,
+ Context context,
+ CarrierConfigTracker carrierConfigTracker,
+ SlotIndexResolver slotIndexResolver,
+ MobileUiAdapter mobileUiAdapter,
+ MobileContextProvider mobileContextProvider,
+ StatusBarPipelineFlags statusBarPipelineFlags
+ ) {
mActivityStarter = activityStarter;
mHandler = handler;
mLooper = looper;
@@ -399,6 +491,9 @@ public class ShadeCarrierGroupController {
mContext = context;
mCarrierConfigTracker = carrierConfigTracker;
mSlotIndexResolver = slotIndexResolver;
+ mMobileUiAdapter = mobileUiAdapter;
+ mMobileContextProvider = mobileContextProvider;
+ mStatusBarPipelineFlags = statusBarPipelineFlags;
}
public Builder setShadeCarrierGroup(ShadeCarrierGroup view) {
@@ -407,9 +502,20 @@ public class ShadeCarrierGroupController {
}
public ShadeCarrierGroupController build() {
- return new ShadeCarrierGroupController(mView, mActivityStarter, mHandler, mLooper,
- mNetworkController, mCarrierTextControllerBuilder, mContext,
- mCarrierConfigTracker, mSlotIndexResolver);
+ return new ShadeCarrierGroupController(
+ mView,
+ mActivityStarter,
+ mHandler,
+ mLooper,
+ mNetworkController,
+ mCarrierTextControllerBuilder,
+ mContext,
+ mCarrierConfigTracker,
+ mSlotIndexResolver,
+ mMobileUiAdapter,
+ mMobileContextProvider,
+ mStatusBarPipelineFlags
+ );
}
}
@@ -448,4 +554,15 @@ public class ShadeCarrierGroupController {
return SubscriptionManager.getSlotIndex(subscriptionId);
}
}
+
+ @VisibleForTesting
+ static class IconData {
+ public final int subId;
+ public final int slotIndex;
+
+ IconData(int subId, int slotIndex) {
+ this.subId = subId;
+ this.slotIndex = slotIndex;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocation.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocation.kt
index 5ace22695ec37..32e5c355889a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocation.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocation.kt
@@ -24,4 +24,6 @@ enum class StatusBarLocation {
KEYGUARD,
/** Quick settings (inside the shade). */
QS,
+ /** ShadeCarrierGroup (above QS status bar in expanded mode). */
+ SHADE_CARRIER_GROUP,
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
index 6e51ed0eba378..c695773086082 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt
@@ -18,6 +18,9 @@ package com.android.systemui.statusbar.pipeline
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.shade.carrier.ShadeCarrierGroup
import javax.inject.Inject
/** All flagging methods related to the new status bar pipeline (see b/238425913). */
@@ -26,10 +29,18 @@ class StatusBarPipelineFlags
@Inject
constructor(
context: Context,
+ private val featureFlags: FeatureFlags,
) {
private val mobileSlot = context.getString(com.android.internal.R.string.status_bar_mobile)
private val wifiSlot = context.getString(com.android.internal.R.string.status_bar_wifi)
+ /**
+ * True if we should display the mobile icons in the [ShadeCarrierGroup] using the new status
+ * bar Data pipeline.
+ */
+ fun useNewShadeCarrierGroupMobileIcons(): Boolean =
+ featureFlags.isEnabled(Flags.NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS)
+
/**
* For convenience in the StatusBarIconController, we want to gate some actions based on slot
* name and the flag together.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index 78231e28803eb..99ed2d99c749b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -60,6 +60,19 @@ sealed interface NetworkNameModel : Diffable {
}
}
+ /** This name has been derived from SubscriptionModel. see [SubscriptionModel] */
+ data class SubscriptionDerived(override val name: String) : NetworkNameModel {
+ override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) {
+ if (prevVal !is SubscriptionDerived || prevVal.name != name) {
+ row.logChange(COL_NETWORK_NAME, "SubscriptionDerived($name)")
+ }
+ }
+
+ override fun logFull(row: TableRowLogger) {
+ row.logChange(COL_NETWORK_NAME, "SubscriptionDerived($name)")
+ }
+ }
+
/**
* This name has been derived from the sim via
* [android.telephony.TelephonyManager.getSimOperatorName].
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt
index 16c4027ef6459..27f6df4c26e15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SubscriptionModel.kt
@@ -34,4 +34,7 @@ data class SubscriptionModel(
/** Subscriptions in the same group may be filtered or treated as a single subscription */
val groupUuid: ParcelUuid? = null,
+
+ /** Text representing the name for this connection */
+ val carrierName: String,
)
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 c1af6df12bd12..a89b1b2db6b31 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
@@ -115,9 +115,17 @@ interface MobileConnectionRepository {
*/
val cdmaRoaming: StateFlow
- /** The service provider name for this network connection, or the default name */
+ /** The service provider name for this network connection, or the default name. */
val networkName: StateFlow
+ /**
+ * The service provider name for this network connection, or the default name.
+ *
+ * TODO(b/296600321): De-duplicate this field with [networkName] after determining the data
+ * provided is identical
+ */
+ val carrierName: StateFlow
+
/**
* True if this type of connection is allowed while airplane mode is on, and false otherwise.
*/
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
index 17d20c2978616..c576b822da158 100644
--- 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
@@ -184,7 +184,10 @@ class DemoMobileConnectionRepository(
override val cdmaRoaming = MutableStateFlow(false)
- override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived("demo network"))
+ override val networkName = MutableStateFlow(NetworkNameModel.IntentDerived(DEMO_CARRIER_NAME))
+
+ override val carrierName =
+ MutableStateFlow(NetworkNameModel.SubscriptionDerived(DEMO_CARRIER_NAME))
override val isAllowedDuringAirplaneMode = MutableStateFlow(false)
@@ -200,6 +203,7 @@ class DemoMobileConnectionRepository(
// 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)
+ carrierName.value = NetworkNameModel.SubscriptionDerived("${event.name} ${event.subId}")
_carrierId.value = event.carrierId ?: INVALID_SUBSCRIPTION_ID
@@ -227,6 +231,7 @@ class DemoMobileConnectionRepository(
// 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)
+ carrierName.value = NetworkNameModel.SubscriptionDerived(CARRIER_MERGED_NAME)
// TODO(b/276943904): is carrierId a thing with carrier merged networks?
_carrierId.value = INVALID_SUBSCRIPTION_ID
numberOfLevels.value = event.numberOfLevels
@@ -248,6 +253,7 @@ class DemoMobileConnectionRepository(
}
companion object {
+ private const val DEMO_CARRIER_NAME = "Demo Carrier"
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 0e4ceebcc8548..ee13d93e735d2 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
@@ -92,9 +92,12 @@ constructor(
private fun maybeCreateSubscription(subId: Int) {
if (!subscriptionInfoCache.containsKey(subId)) {
- SubscriptionModel(subscriptionId = subId, isOpportunistic = false).also {
- subscriptionInfoCache[subId] = it
- }
+ SubscriptionModel(
+ subscriptionId = subId,
+ isOpportunistic = false,
+ carrierName = DEFAULT_CARRIER_NAME,
+ )
+ .also { subscriptionInfoCache[subId] = it }
_subscriptions.value = subscriptionInfoCache.values.toList()
}
@@ -327,6 +330,7 @@ constructor(
private const val TAG = "DemoMobileConnectionsRepo"
private const val DEFAULT_SUB_ID = 1
+ private const val DEFAULT_CARRIER_NAME = "demo carrier"
}
}
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 65f4866838371..28be3be289284 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
@@ -108,6 +108,8 @@ class CarrierMergedConnectionRepository(
NetworkNameModel.SimDerived(telephonyManager.simOperatorName),
)
+ override val carrierName: StateFlow = networkName
+
override val numberOfLevels: StateFlow =
wifiRepository.wifiNetwork
.map {
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 8ba7d2197c141..ee11c06ef3f5a 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
@@ -22,6 +22,7 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -47,6 +48,7 @@ class FullMobileConnectionRepository(
override val subId: Int,
startingIsCarrierMerged: Boolean,
override val tableLogBuffer: TableLogBuffer,
+ subscriptionModel: StateFlow,
private val defaultNetworkName: NetworkNameModel,
private val networkNameSeparator: String,
@Application scope: CoroutineScope,
@@ -80,6 +82,7 @@ class FullMobileConnectionRepository(
mobileRepoFactory.build(
subId,
tableLogBuffer,
+ subscriptionModel,
defaultNetworkName,
networkNameSeparator,
)
@@ -287,6 +290,16 @@ class FullMobileConnectionRepository(
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.networkName.value)
+ override val carrierName =
+ activeRepo
+ .flatMapLatest { it.carrierName }
+ .logDiffsForTable(
+ tableLogBuffer,
+ columnPrefix = "",
+ initialValue = activeRepo.value.carrierName.value,
+ )
+ .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.carrierName.value)
+
override val isAllowedDuringAirplaneMode =
activeRepo
.flatMapLatest { it.isAllowedDuringAirplaneMode }
@@ -307,6 +320,7 @@ class FullMobileConnectionRepository(
fun build(
subId: Int,
startingIsCarrierMerged: Boolean,
+ subscriptionModel: StateFlow,
defaultNetworkName: NetworkNameModel,
networkNameSeparator: String,
): FullMobileConnectionRepository {
@@ -317,6 +331,7 @@ class FullMobileConnectionRepository(
subId,
startingIsCarrierMerged,
mobileLogger,
+ subscriptionModel,
defaultNetworkName,
networkNameSeparator,
scope,
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 aadc975a10dea..1f1ac92b39568 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
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameMode
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
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.data.model.toDataConnectionType
import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
@@ -80,6 +81,7 @@ import kotlinx.coroutines.flow.stateIn
@OptIn(ExperimentalCoroutinesApi::class)
class MobileConnectionRepositoryImpl(
override val subId: Int,
+ subscriptionModel: StateFlow,
defaultNetworkName: NetworkNameModel,
networkNameSeparator: String,
private val telephonyManager: TelephonyManager,
@@ -281,6 +283,14 @@ class MobileConnectionRepositoryImpl(
}
.stateIn(scope, SharingStarted.WhileSubscribed(), DEFAULT_NUM_LEVELS)
+ override val carrierName =
+ subscriptionModel
+ .map {
+ it?.let { model -> NetworkNameModel.SubscriptionDerived(model.carrierName) }
+ ?: defaultNetworkName
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
+
/**
* There are a few cases where we will need to poll [TelephonyManager] so we can update some
* internal state where callbacks aren't provided. Any of those events should be merged into
@@ -350,11 +360,13 @@ class MobileConnectionRepositoryImpl(
fun build(
subId: Int,
mobileLogger: TableLogBuffer,
+ subscriptionModel: StateFlow,
defaultNetworkName: NetworkNameModel,
networkNameSeparator: String,
): MobileConnectionRepository {
return MobileConnectionRepositoryImpl(
subId,
+ subscriptionModel,
defaultNetworkName,
networkNameSeparator,
telephonyManager.createForSubscriptionId(subId),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index 54948a4a41c83..67b04db644639 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -319,10 +319,17 @@ constructor(
@VisibleForTesting fun getSubIdRepoCache() = subIdRepositoryCache
+ private fun subscriptionModelForSubId(subId: Int): StateFlow {
+ return subscriptions
+ .map { list -> list.firstOrNull { model -> model.subscriptionId == subId } }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+ }
+
private fun createRepositoryForSubId(subId: Int): FullMobileConnectionRepository {
return fullMobileRepoFactory.build(
subId,
isCarrierMerged(subId),
+ subscriptionModelForSubId(subId),
defaultNetworkName,
networkNameSeparator,
)
@@ -373,6 +380,7 @@ constructor(
subscriptionId = subscriptionId,
isOpportunistic = isOpportunistic,
groupUuid = groupUuid,
+ carrierName = carrierName.toString(),
)
companion object {
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 1a138272d67c3..4cfde5bd5622e 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
@@ -92,6 +92,22 @@ interface MobileIconInteractor {
*/
val networkName: StateFlow
+ /**
+ * Provider name for this network connection. The name can be one of 3 values:
+ * 1. The default network name, if one is configured
+ * 2. A name provided by the [SubscriptionModel] of this network connection
+ * 3. Or, in the case where the repository sends us the default network name, we check for an
+ * override in [connectionInfo.operatorAlphaShort], a value that is derived from
+ * [ServiceState]
+ *
+ * TODO(b/296600321): De-duplicate this field with [networkName] after determining the data
+ * provided is identical
+ */
+ val carrierName: StateFlow
+
+ /** True if there is only one active subscription. */
+ val isSingleCarrier: StateFlow
+
/** True if this line of service is emergency-only */
val isEmergencyOnly: StateFlow
@@ -126,6 +142,7 @@ class MobileIconInteractorImpl(
defaultSubscriptionHasDataEnabled: StateFlow,
override val alwaysShowDataRatIcon: StateFlow,
override val alwaysUseCdmaLevel: StateFlow,
+ override val isSingleCarrier: StateFlow,
override val mobileIsDefault: StateFlow,
defaultMobileIconMapping: StateFlow