From bb7f96387d0a035c2f0e7ac19675012b854f6623 Mon Sep 17 00:00:00 2001 From: Evan Laird Date: Fri, 4 Nov 2022 13:26:25 -0400 Subject: [PATCH] Enable network type icon overlays by carrier Id This CL builds out a new configuration resource `carrierid_icon_overrides`, and a format that allows for overriding a known network type with an arbitrary icon. We store a mapping of all known carrierId overrides that exist, and check for an override for the `carrierId & networkType` combination at runtime. This CL also caches the calculation in SystemUI since it represents a new expensive calculation potential at the time of display for the icon. Lastly, add demo mode command parsing for carrierId Test: atest MobileStateTest; atest NetworkControllerDataTest Test: manual using `-e carrierid ` network subcommand Bug: 241996752 Change-Id: Id0e8acf179db5c3a70f4caf31e58f8d8040690a0 --- .../ic_5g_plus_mobiledata_default.xml | 33 ++++ .../res/values/carrierid_icon_overrides.xml | 32 ++++ .../mobile/MobileIconCarrierIdOverrides.kt | 142 ++++++++++++++++++ .../MobileIconCarrierIdOverridesTest.java | 140 +++++++++++++++++ .../connectivity/MobileSignalController.java | 28 ++-- .../MobileSignalControllerFactory.kt | 3 + .../statusbar/connectivity/MobileState.kt | 35 ++++- .../connectivity/NetworkControllerImpl.java | 26 +++- .../connectivity/NetworkTypeResIdCache.kt | 78 ++++++++++ .../connectivity/ui/MobileContextProvider.kt | 7 + .../pipeline/mobile/util/MobileMappings.kt | 4 + .../MobileIconCarrierIdOverridesFake.kt | 48 ++++++ .../connectivity/MobileStateTest.java | 137 ----------------- .../statusbar/connectivity/MobileStateTest.kt | 119 +++++++++++++++ .../NetworkControllerBaseTest.java | 8 +- .../NetworkControllerDataTest.java | 63 ++++++++ .../connectivity/NetworkTypeResIdCacheTest.kt | 83 ++++++++++ .../mobile/util/FakeMobileMappingsProxy.kt | 32 +++- 18 files changed, 865 insertions(+), 153 deletions(-) create mode 100644 packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml create mode 100644 packages/SettingsLib/res/values/carrierid_icon_overrides.xml create mode 100644 packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt create mode 100644 packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt diff --git a/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml new file mode 100644 index 0000000000000..46abff81d38fd --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata_default.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/packages/SettingsLib/res/values/carrierid_icon_overrides.xml b/packages/SettingsLib/res/values/carrierid_icon_overrides.xml new file mode 100644 index 0000000000000..d2ae52d8347a6 --- /dev/null +++ b/packages/SettingsLib/res/values/carrierid_icon_overrides.xml @@ -0,0 +1,32 @@ + + + + + + + 5G_PLUS + @drawable/ic_5g_plus_mobiledata_default + + \ No newline at end of file diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt new file mode 100644 index 0000000000000..a0395b5592915 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileIconCarrierIdOverrides.kt @@ -0,0 +1,142 @@ +/* + * 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.settingslib.mobile + +import android.annotation.DrawableRes +import android.content.res.Resources +import android.content.res.TypedArray +import android.util.Log +import androidx.annotation.VisibleForTesting +import com.android.settingslib.R +import com.android.settingslib.SignalIcon.MobileIconGroup + +/** + * This class defines a network type (3G, 4G, etc.) override mechanism on a per-carrierId basis. + * + * Traditionally, carrier-customized network type iconography was achieved using the `MCC/MNC` + * resource qualifiers, and swapping out the drawable resource by name. It would look like this: + * + * res/ + * drawable/ + * 3g_mobiledata_icon.xml + * drawable-MCC-MNC/ + * 3g_mobiledata_icon.xml + * + * This would mean that, provided a context created with this MCC/MNC configuration set, loading + * the network type icon through [MobileIconGroup] would provide a carrier-defined network type + * icon rather than the AOSP-defined default. + * + * The MCC/MNC mechanism no longer can fully define carrier-specific network type icons, because + * there is no longer a 1:1 mapping between MCC/MNC and carrier. With the advent of MVNOs, multiple + * carriers can have the same MCC/MNC value, but wish to differentiate based on their carrier ID. + * CarrierId is a newer concept than MCC/MNC, and provides more granularity when it comes to + * determining the carrier (e.g. MVNOs can share MCC/MNC values with the network owner), therefore + * it can fit all of the same use cases currently handled by `MCC/MNC`, without the need to apply a + * configuration context in order to get the proper UI for a given SIM icon. + * + * NOTE: CarrierId icon overrides will always take precedence over those defined using `MCC/MNC` + * resource qualifiers. + * + * [MAPPING] encodes the relationship between CarrierId and the corresponding override array + * that exists in the config.xml. An alternative approach could be to generate the resource name + * by string concatenation at run-time: + * + * val resName = "carrierId_$carrierId_iconOverrides" + * val override = resources.getResourceIdentifier(resName) + * + * However, that's going to be far less efficient until MAPPING grows to a sufficient size. For now, + * given a relatively small number of entries, we should just maintain the mapping here. + */ +interface MobileIconCarrierIdOverrides { + @DrawableRes + fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int + fun carrierIdEntryExists(carrierId: Int): Boolean +} + +class MobileIconCarrierIdOverridesImpl : MobileIconCarrierIdOverrides { + @DrawableRes + override fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int { + val resId = MAPPING[carrierId] ?: return 0 + val ta = resources.obtainTypedArray(resId) + val map = parseNetworkIconOverrideTypedArray(ta) + ta.recycle() + return map[networkType] ?: 0 + } + + override fun carrierIdEntryExists(carrierId: Int) = + overrideExists(carrierId, MAPPING) + + companion object { + private const val TAG = "MobileIconOverrides" + /** + * This map maintains the lookup from the canonical carrier ID (see below link) to the + * corresponding overlay resource. New overrides should add an entry below in order to + * change the network type icon resources based on carrier ID + * + * Refer to the link below for the canonical mapping maintained in AOSP: + * https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb + */ + private val MAPPING = mapOf( + // 2032 == Xfinity Mobile + 2032 to R.array.carrierId_2032_iconOverrides, + ) + + /** + * Parse `carrierId_XXXX_iconOverrides` for a particular network type. The resource file + * "carrierid_icon_overrides.xml" defines a TypedArray format for overriding specific + * network type icons (a.k.a. RAT icons) for a particular carrier ID. The format is defined + * as an array of (network type name, drawable) pairs: + * () + // The array is defined as Pair(String, resourceId), so walk by 2 + for (i in 0 until ta.length() step 2) { + val key = ta.getString(i) + val override = ta.getResourceId(i + 1, 0) + if (key == null || override == 0) { + Log.w(TAG, "Invalid override found. Skipping") + continue + } + result[key] = override + } + + return result + } + + @JvmStatic + private fun overrideExists(carrierId: Int, mapping: Map): Boolean = + mapping.containsKey(carrierId) + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java new file mode 100644 index 0000000000000..740261d3bac20 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/mobile/MobileIconCarrierIdOverridesTest.java @@ -0,0 +1,140 @@ +/* + * 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.settingslib.mobile; + +import static com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl.parseNetworkIconOverrideTypedArray; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.content.res.TypedArray; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.util.Map; + +@RunWith(RobolectricTestRunner.class) +public final class MobileIconCarrierIdOverridesTest { + private static final String OVERRIDE_ICON_1_NAME = "name_1"; + private static final int OVERRIDE_ICON_1_RES = 1; + + private static final String OVERRIDE_ICON_2_NAME = "name_2"; + private static final int OVERRIDE_ICON_2_RES = 2; + + NetworkOverrideTypedArrayMock mResourceMock; + + @Before + public void setUp() { + mResourceMock = new NetworkOverrideTypedArrayMock( + new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME }, + new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES } + ); + } + + @Test + public void testParse_singleOverride() { + mResourceMock.setOverrides( + new String[] { OVERRIDE_ICON_1_NAME }, + new int[] { OVERRIDE_ICON_1_RES } + ); + + Map parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock()); + + assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES); + } + + @Test + public void testParse_multipleOverrides() { + mResourceMock.setOverrides( + new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME }, + new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES } + ); + + Map parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock()); + + assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isEqualTo(OVERRIDE_ICON_2_RES); + assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES); + } + + @Test + public void testParse_nonexistentKey_isNull() { + mResourceMock.setOverrides( + new String[] { OVERRIDE_ICON_1_NAME }, + new int[] { OVERRIDE_ICON_1_RES } + ); + + Map parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock()); + + assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isNull(); + } + + static class NetworkOverrideTypedArrayMock { + private Object[] mInterleaved; + + private final TypedArray mMockTypedArray = mock(TypedArray.class); + + NetworkOverrideTypedArrayMock( + String[] networkTypes, + int[] iconOverrides) { + + mInterleaved = interleaveTypes(networkTypes, iconOverrides); + + doAnswer(invocation -> { + return mInterleaved[(int) invocation.getArgument(0)]; + }).when(mMockTypedArray).getString(/* index */ anyInt()); + + doAnswer(invocation -> { + return mInterleaved[(int) invocation.getArgument(0)]; + }).when(mMockTypedArray).getResourceId(/* index */ anyInt(), /* default */ anyInt()); + + when(mMockTypedArray.length()).thenAnswer(invocation -> { + return mInterleaved.length; + }); + } + + TypedArray getMock() { + return mMockTypedArray; + } + + void setOverrides(String[] types, int[] resIds) { + mInterleaved = interleaveTypes(types, resIds); + } + + private Object[] interleaveTypes(String[] strs, int[] ints) { + assertThat(strs.length).isEqualTo(ints.length); + + Object[] ret = new Object[strs.length * 2]; + + // Keep track of where we are in the interleaved array, but iterate the overrides + int interleavedIndex = 0; + for (int i = 0; i < strs.length; i++) { + ret[interleavedIndex] = strs[i]; + interleavedIndex += 1; + ret[interleavedIndex] = ints[i]; + interleavedIndex += 1; + } + return ret; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index 5cf1abc18274e..035b90faf7dad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -15,9 +15,7 @@ */ package com.android.systemui.statusbar.connectivity; -import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons; -import static com.android.settingslib.mobile.MobileMappings.getIconKey; -import static com.android.settingslib.mobile.MobileMappings.mapIconSets; +import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; import android.content.Context; import android.content.Intent; @@ -46,6 +44,7 @@ import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; +import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy; import com.android.systemui.util.CarrierConfigTracker; import java.io.PrintWriter; @@ -63,6 +62,7 @@ public class MobileSignalController extends SignalController { val columns = listOf("dataSim", + "carrierId", "networkName", "networkNameData", "dataConnected", @@ -178,6 +206,7 @@ internal class MobileState( "showQuickSettingsRatIcon", "voiceServiceState", "isInService", + "networkTypeIconCache", "serviceState", "signalStrength", "displayInfo") @@ -187,6 +216,7 @@ internal class MobileState( override fun tableData(): List { val columns = listOf(dataSim, + carrierId, networkName, networkNameData, dataConnected, @@ -201,6 +231,7 @@ internal class MobileState( showQuickSettingsRatIcon(), getVoiceServiceState(), isInService(), + networkTypeResIdCache, serviceState?.minLog() ?: "(null)", signalStrength?.minLog() ?: "(null)", telephonyDisplayInfo).map { it.toString() } @@ -217,6 +248,7 @@ internal class MobileState( if (networkName != other.networkName) return false if (networkNameData != other.networkNameData) return false + if (carrierId != other.carrierId) return false if (dataSim != other.dataSim) return false if (dataConnected != other.dataConnected) return false if (isEmergency != other.isEmergency) return false @@ -238,6 +270,7 @@ internal class MobileState( var result = super.hashCode() result = 31 * result + (networkName?.hashCode() ?: 0) result = 31 * result + (networkNameData?.hashCode() ?: 0) + result = 31 * result + (carrierId.hashCode()) result = 31 * result + dataSim.hashCode() result = 31 * result + dataConnected.hashCode() result = 31 * result + isEmergency.hashCode() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 402217dac185d..3cc53c16f28be 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -22,6 +22,7 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT; import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE; import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import android.annotation.Nullable; import android.content.BroadcastReceiver; @@ -139,7 +140,7 @@ public class NetworkControllerImpl extends BroadcastReceiver private final MobileSignalControllerFactory mMobileFactory; private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener; - private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + private int mActiveMobileDataSubscription = INVALID_SUBSCRIPTION_ID; // Subcontrollers. @VisibleForTesting @@ -503,6 +504,7 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED); + filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler); mListening = true; @@ -793,6 +795,20 @@ public class NetworkControllerImpl extends BroadcastReceiver mConfig = Config.readConfig(mContext); mReceiverHandler.post(this::handleConfigurationChanged); break; + + case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: { + // Notify the relevant MobileSignalController of the change + int subId = intent.getIntExtra( + TelephonyManager.EXTRA_SUBSCRIPTION_ID, + INVALID_SUBSCRIPTION_ID + ); + if (SubscriptionManager.isValidSubscriptionId(subId)) { + if (mMobileSignalControllers.indexOfKey(subId) >= 0) { + mMobileSignalControllers.get(subId).handleBroadcast(intent); + } + } + } + break; case Intent.ACTION_SIM_STATE_CHANGED: // Avoid rebroadcast because SysUI is direct boot aware. if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { @@ -820,7 +836,7 @@ public class NetworkControllerImpl extends BroadcastReceiver break; default: int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, - SubscriptionManager.INVALID_SUBSCRIPTION_ID); + INVALID_SUBSCRIPTION_ID); if (SubscriptionManager.isValidSubscriptionId(subId)) { if (mMobileSignalControllers.indexOfKey(subId) >= 0) { mMobileSignalControllers.get(subId).handleBroadcast(intent); @@ -1336,6 +1352,9 @@ public class NetworkControllerImpl extends BroadcastReceiver String slotString = args.getString("slot"); int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); slot = MathUtils.constrain(slot, 0, 8); + String carrierIdString = args.getString("carrierid"); + int carrierId = TextUtils.isEmpty(carrierIdString) ? 0 + : Integer.parseInt(carrierIdString); // Ensure we have enough sim slots List subs = new ArrayList<>(); while (mMobileSignalControllers.size() <= slot) { @@ -1347,6 +1366,9 @@ public class NetworkControllerImpl extends BroadcastReceiver } // Hack to index linearly for easy use. MobileSignalController controller = mMobileSignalControllers.valueAt(slot); + if (carrierId != 0) { + controller.getState().setCarrierId(carrierId); + } controller.getState().dataSim = datatype != null; controller.getState().isDefault = datatype != null; controller.getState().dataConnected = datatype != null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt new file mode 100644 index 0000000000000..9be7ee99cf022 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCache.kt @@ -0,0 +1,78 @@ +/* + * 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.connectivity + +import android.annotation.DrawableRes +import android.content.Context +import com.android.settingslib.SignalIcon.MobileIconGroup +import com.android.settingslib.mobile.MobileIconCarrierIdOverrides +import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl + +/** + * Cache for network type resource IDs. + * + * The default framework behavior is to have a statically defined icon per network type. See + * [MobileIconGroup] for the standard mapping. + * + * For the case of carrierId-defined overrides, we want to check [MobileIconCarrierIdOverrides] for + * an existing icon override, and cache the result of the operation + */ +class NetworkTypeResIdCache( + private val overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl() +) { + @DrawableRes private var cachedResId: Int = 0 + private var lastCarrierId: Int? = null + private var lastIconGroup: MobileIconGroup? = null + private var isOverridden: Boolean = false + + @DrawableRes + fun get(iconGroup: MobileIconGroup, carrierId: Int, context: Context): Int { + if (lastCarrierId != carrierId || lastIconGroup != iconGroup) { + lastCarrierId = carrierId + lastIconGroup = iconGroup + + val maybeOverride = calculateOverriddenIcon(iconGroup, carrierId, context) + if (maybeOverride > 0) { + cachedResId = maybeOverride + isOverridden = true + } else { + cachedResId = iconGroup.dataType + isOverridden = false + } + } + + return cachedResId + } + + override fun toString(): String { + return "networkTypeResIdCache={id=$cachedResId, isOverridden=$isOverridden}" + } + + @DrawableRes + private fun calculateOverriddenIcon( + iconGroup: MobileIconGroup, + carrierId: Int, + context: Context, + ): Int { + val name = iconGroup.name + if (!overrides.carrierIdEntryExists(carrierId)) { + return 0 + } + + return overrides.getOverrideFor(carrierId, name, context.resources) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt index a02dd34903413..42b874fd71561 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt @@ -37,6 +37,13 @@ import javax.inject.Inject * own [Configuration] and track resources based on the full set of available mcc-mnc combinations. * * (for future reference: b/240555502 is the initiating bug for this) + * + * NOTE: MCC/MNC qualifiers are not sufficient to fully describe a network type icon qualified by + * network type + carrier ID. This class exists to keep the legacy behavior of using the MCC/MNC + * resource qualifiers working, but if a carrier-specific icon is requested, then the override + * provided by [MobileIconCarrierIdOverrides] will take precedence. + * + * TODO(b/258503704): consider removing this class in favor of the `carrierId` overrides */ @SysUISingleton class MobileContextProvider diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt index 60bd0383f8c72..501467f130075 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/util/MobileMappings.kt @@ -32,6 +32,7 @@ import javax.inject.Inject interface MobileMappingsProxy { fun mapIconSets(config: Config): Map fun getDefaultIcons(config: Config): MobileIconGroup + fun getIconKey(displayInfo: TelephonyDisplayInfo): String fun toIconKey(@NetworkType networkType: Int): String fun toIconKeyOverride(@NetworkType networkType: Int): String } @@ -44,6 +45,9 @@ class MobileMappingsProxyImpl @Inject constructor() : MobileMappingsProxy { override fun getDefaultIcons(config: Config): MobileIconGroup = MobileMappings.getDefaultIcons(config) + override fun getIconKey(displayInfo: TelephonyDisplayInfo): String = + MobileMappings.getIconKey(displayInfo) + override fun toIconKey(@NetworkType networkType: Int): String = MobileMappings.toIconKey(networkType) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt new file mode 100644 index 0000000000000..62b4e7b79f5e4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileIconCarrierIdOverridesFake.kt @@ -0,0 +1,48 @@ +/* + * 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.connectivity + +import android.content.res.Resources +import com.android.settingslib.mobile.MobileIconCarrierIdOverrides + +typealias CarrierId = Int + +typealias NetworkType = String + +typealias ResId = Int + +class MobileIconCarrierIdOverridesFake : MobileIconCarrierIdOverrides { + /** Backing for [carrierIdEntryExists] */ + var overriddenIds = mutableSetOf() + + /** Backing for [getOverrideFor]. Map should be Map< CarrierId < NetworkType, ResId>> */ + var overridesByCarrierId = mutableMapOf>() + + override fun getOverrideFor( + carrierId: CarrierId, + networkType: NetworkType, + resources: Resources + ): ResId { + if (!overriddenIds.contains(carrierId)) return 0 + + return overridesByCarrierId[carrierId]?.get(networkType) ?: 0 + } + + override fun carrierIdEntryExists(carrierId: Int): Boolean { + return overriddenIds.contains(carrierId) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java deleted file mode 100644 index 7ddfde370afa0..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2021 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.connectivity; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import android.test.suitebuilder.annotation.SmallTest; -import android.testing.AndroidTestingRunner; - -import com.android.settingslib.mobile.TelephonyIcons; -import com.android.systemui.SysuiTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -public class MobileStateTest extends SysuiTestCase { - - private final MobileState mState = new MobileState(); - - @Before - public void setUp() { - } - - @Test - public void testIsDataDisabledOrNotDefault_dataDisabled() { - mState.iconGroup = TelephonyIcons.DATA_DISABLED; - mState.userSetup = true; - - assertTrue(mState.isDataDisabledOrNotDefault()); - } - - @Test - public void testIsDataDisabledOrNotDefault_notDefaultData() { - mState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA; - mState.userSetup = true; - - assertTrue(mState.isDataDisabledOrNotDefault()); - } - - @Test - public void testIsDataDisabledOrNotDefault_notDisabled() { - mState.iconGroup = TelephonyIcons.G; - mState.userSetup = true; - - assertFalse(mState.isDataDisabledOrNotDefault()); - } - - @Test - public void testHasActivityIn_noData_noActivity() { - mState.dataConnected = false; - mState.carrierNetworkChangeMode = false; - mState.activityIn = false; - - assertFalse(mState.hasActivityIn()); - } - - @Test - public void testHasActivityIn_noData_activityIn() { - mState.dataConnected = false; - mState.carrierNetworkChangeMode = false; - mState.activityIn = true; - - assertFalse(mState.hasActivityIn()); - } - - @Test - public void testHasActivityIn_dataConnected_activityIn() { - mState.dataConnected = true; - mState.carrierNetworkChangeMode = false; - mState.activityIn = true; - - assertTrue(mState.hasActivityIn()); - } - - @Test - public void testHasActivityIn_carrierNetworkChange() { - mState.dataConnected = true; - mState.carrierNetworkChangeMode = true; - mState.activityIn = true; - - assertFalse(mState.hasActivityIn()); - } - - @Test - public void testHasActivityOut_noData_noActivity() { - mState.dataConnected = false; - mState.carrierNetworkChangeMode = false; - mState.activityOut = false; - - assertFalse(mState.hasActivityOut()); - } - - @Test - public void testHasActivityOut_noData_activityOut() { - mState.dataConnected = false; - mState.carrierNetworkChangeMode = false; - mState.activityOut = true; - - assertFalse(mState.hasActivityOut()); - } - - @Test - public void testHasActivityOut_dataConnected_activityOut() { - mState.dataConnected = true; - mState.carrierNetworkChangeMode = false; - mState.activityOut = true; - - assertTrue(mState.hasActivityOut()); - } - - @Test - public void testHasActivityOut_carrierNetworkChange() { - mState.dataConnected = true; - mState.carrierNetworkChangeMode = true; - mState.activityOut = true; - - assertFalse(mState.hasActivityOut()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt new file mode 100644 index 0000000000000..a226ded06111e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/MobileStateTest.kt @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2021 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.connectivity + +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import com.android.settingslib.mobile.TelephonyIcons +import com.android.systemui.SysuiTestCase +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class MobileStateTest : SysuiTestCase() { + + private val state = MobileState() + @Before fun setUp() {} + + @Test + fun testIsDataDisabledOrNotDefault_dataDisabled() { + state.iconGroup = TelephonyIcons.DATA_DISABLED + state.userSetup = true + assertTrue(state.isDataDisabledOrNotDefault) + } + + @Test + fun testIsDataDisabledOrNotDefault_notDefaultData() { + state.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA + state.userSetup = true + assertTrue(state.isDataDisabledOrNotDefault) + } + + @Test + fun testIsDataDisabledOrNotDefault_notDisabled() { + state.iconGroup = TelephonyIcons.G + state.userSetup = true + assertFalse(state.isDataDisabledOrNotDefault) + } + + @Test + fun testHasActivityIn_noData_noActivity() { + state.dataConnected = false + state.carrierNetworkChangeMode = false + state.activityIn = false + assertFalse(state.hasActivityIn()) + } + + @Test + fun testHasActivityIn_noData_activityIn() { + state.dataConnected = false + state.carrierNetworkChangeMode = false + state.activityIn = true + assertFalse(state.hasActivityIn()) + } + + @Test + fun testHasActivityIn_dataConnected_activityIn() { + state.dataConnected = true + state.carrierNetworkChangeMode = false + state.activityIn = true + assertTrue(state.hasActivityIn()) + } + + @Test + fun testHasActivityIn_carrierNetworkChange() { + state.dataConnected = true + state.carrierNetworkChangeMode = true + state.activityIn = true + assertFalse(state.hasActivityIn()) + } + + @Test + fun testHasActivityOut_noData_noActivity() { + state.dataConnected = false + state.carrierNetworkChangeMode = false + state.activityOut = false + assertFalse(state.hasActivityOut()) + } + + @Test + fun testHasActivityOut_noData_activityOut() { + state.dataConnected = false + state.carrierNetworkChangeMode = false + state.activityOut = true + assertFalse(state.hasActivityOut()) + } + + @Test + fun testHasActivityOut_dataConnected_activityOut() { + state.dataConnected = true + state.carrierNetworkChangeMode = false + state.activityOut = true + assertTrue(state.hasActivityOut()) + } + + @Test + fun testHasActivityOut_carrierNetworkChange() { + state.dataConnected = true + state.carrierNetworkChangeMode = true + state.activityOut = true + assertFalse(state.hasActivityOut()) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index 9c65fac1af458..9c870b5aa3636 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -71,6 +71,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.log.LogBuffer; +import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.telephony.TelephonyListenerManager; @@ -125,6 +126,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected CarrierConfigTracker mCarrierConfigTracker; protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); protected Handler mMainHandler; + // Use a real mobile mappings object since lots of tests rely on it + protected FakeMobileMappingsProxy mMobileMappingsProxy = new FakeMobileMappingsProxy(); protected WifiStatusTrackerFactory mWifiStatusTrackerFactory; protected MobileSignalControllerFactory mMobileFactory; @@ -219,10 +222,13 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mWifiStatusTrackerFactory = new WifiStatusTrackerFactory( mContext, mMockWm, mMockNsm, mMockCm, mMainHandler); + // Most of these tests rely on the actual MobileMappings behavior + mMobileMappingsProxy.setUseRealImpl(true); mMobileFactory = new MobileSignalControllerFactory( mContext, mCallbackHandler, - mCarrierConfigTracker + mCarrierConfigTracker, + mMobileMappingsProxy ); mNetworkController = new NetworkControllerImpl(mContext, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index 4bed4a19b3d9b..1d112262765eb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -18,12 +18,21 @@ package com.android.systemui.statusbar.connectivity; import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS; +import static android.telephony.TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED; +import static android.telephony.TelephonyManager.EXTRA_CARRIER_ID; +import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID; +import static com.android.settingslib.mobile.TelephonyIcons.NR_5G_PLUS; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import android.content.Intent; import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; @@ -35,6 +44,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import com.android.settingslib.SignalIcon.MobileIconGroup; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import com.android.systemui.dump.DumpManager; @@ -45,6 +55,8 @@ import com.android.systemui.util.CarrierConfigTracker; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.HashMap; + @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper @@ -329,6 +341,57 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { assertFalse(mNetworkController.isMobileDataNetworkInService()); } + @Test + public void mobileSignalController_getsCarrierId() { + when(mMockTm.getSimCarrierId()).thenReturn(1); + setupDefaultSignal(); + + assertEquals(1, mMobileSignalController.getState().getCarrierId()); + } + + @Test + public void mobileSignalController_updatesCarrierId_onChange() { + when(mMockTm.getSimCarrierId()).thenReturn(1); + setupDefaultSignal(); + + // Updates are sent down through this broadcast, we can send the intent directly + Intent intent = new Intent(ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED); + intent.putExtra(EXTRA_SUBSCRIPTION_ID, mSubId); + intent.putExtra(EXTRA_CARRIER_ID, 2); + + mMobileSignalController.handleBroadcast(intent); + + assertEquals(2, mMobileSignalController.getState().getCarrierId()); + } + + @Test + public void networkTypeIcon_hasCarrierIdOverride() { + int fakeCarrier = 1; + int fakeIconOverride = 12345; + int testDataNetType = 100; + String testDataString = "100"; + HashMap testMap = new HashMap<>(); + testMap.put(testDataString, NR_5G_PLUS); + + // Pretend that there is an override for this icon, and this carrier ID + NetworkTypeResIdCache mockCache = mock(NetworkTypeResIdCache.class); + when(mockCache.get(eq(NR_5G_PLUS), eq(fakeCarrier), any())).thenReturn(fakeIconOverride); + + // Turn off the default mobile mapping, so we can override + mMobileMappingsProxy.setUseRealImpl(false); + mMobileMappingsProxy.setIconMap(testMap); + // Use the mocked cache + mMobileSignalController.mCurrentState.setNetworkTypeResIdCache(mockCache); + // Rebuild the network map + mMobileSignalController.setConfiguration(mConfig); + when(mMockTm.getSimCarrierId()).thenReturn(fakeCarrier); + + setupDefaultSignal(); + updateDataConnectionState(TelephonyManager.DATA_CONNECTED, testDataNetType); + + verifyDataIndicators(fakeIconOverride); + } + private void testDataActivity(int direction, boolean in, boolean out) { updateDataActivity(direction); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt new file mode 100644 index 0000000000000..9e73487972e8f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkTypeResIdCacheTest.kt @@ -0,0 +1,83 @@ +/* + * 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.connectivity + +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import com.android.settingslib.SignalIcon.MobileIconGroup +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class NetworkTypeResIdCacheTest : SysuiTestCase() { + private lateinit var cache: NetworkTypeResIdCache + private var overrides = MobileIconCarrierIdOverridesFake() + + @Before + fun setUp() { + cache = NetworkTypeResIdCache(overrides) + } + + @Test + fun carrier1_noOverride_usesDefault() { + assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconDefault1) + } + + @Test + fun carrier1_overridden_usesOverride() { + overrides.overriddenIds.add(CARRIER_1) + overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1) + + assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconOverride1) + } + + @Test + fun carrier1_override_carrier2UsesDefault() { + overrides.overriddenIds.add(CARRIER_1) + overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1) + + assertThat(cache.get(group1, CARRIER_2, context)).isEqualTo(iconDefault1) + } + + @Test + fun carrier1_overrideType1_type2UsesDefault() { + overrides.overriddenIds.add(CARRIER_1) + overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1) + + assertThat(cache.get(group2, CARRIER_1, context)).isEqualTo(iconDefault2) + } + + companion object { + // Simplified icon overrides here + const val CARRIER_1 = 1 + const val CARRIER_2 = 2 + + const val NET_TYPE_1 = "one" + const val iconDefault1 = 123 + const val iconOverride1 = 321 + val group1 = MobileIconGroup(NET_TYPE_1, /* dataContentDesc */ 0, iconDefault1) + + const val NET_TYPE_2 = "two" + const val iconDefault2 = 234 + + val group2 = MobileIconGroup(NET_TYPE_2, /* dataContentDesc*/ 0, iconDefault2) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt index 6d8d902615de1..a052008d48321 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/util/FakeMobileMappingsProxy.kt @@ -16,31 +16,59 @@ package com.android.systemui.statusbar.pipeline.mobile.util +import android.telephony.TelephonyDisplayInfo import com.android.settingslib.SignalIcon.MobileIconGroup import com.android.settingslib.mobile.MobileMappings.Config import com.android.settingslib.mobile.TelephonyIcons class FakeMobileMappingsProxy : MobileMappingsProxy { + // The old [NetworkControllerDataTest] infra requires us to be able to use the real + // impl sometimes + var useRealImpl = false + + private var realImpl = MobileMappingsProxyImpl() private var iconMap = mapOf() private var defaultIcons = TelephonyIcons.THREE_G fun setIconMap(map: Map) { iconMap = map } - override fun mapIconSets(config: Config): Map = iconMap + override fun mapIconSets(config: Config): Map { + if (useRealImpl) { + return realImpl.mapIconSets(config) + } + return iconMap + } fun getIconMap() = iconMap fun setDefaultIcons(group: MobileIconGroup) { defaultIcons = group } - override fun getDefaultIcons(config: Config): MobileIconGroup = defaultIcons + override fun getDefaultIcons(config: Config): MobileIconGroup { + if (useRealImpl) { + return realImpl.getDefaultIcons(config) + } + return defaultIcons + } + + /** This is only used in the old pipeline, use the real impl always */ + override fun getIconKey(displayInfo: TelephonyDisplayInfo): String { + return realImpl.getIconKey(displayInfo) + } + fun getDefaultIcons(): MobileIconGroup = defaultIcons override fun toIconKey(networkType: Int): String { + if (useRealImpl) { + return realImpl.toIconKeyOverride(networkType) + } return networkType.toString() } override fun toIconKeyOverride(networkType: Int): String { + if (useRealImpl) { + return realImpl.toIconKeyOverride(networkType) + } return toIconKey(networkType) + "_override" } }