diff options
7 files changed, 368 insertions, 52 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java index b416738ade4a..39b4b8e16708 100644 --- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java @@ -78,6 +78,9 @@ public class MobileStatusTracker { * Config the MobileStatusTracker to start or stop monitoring platform signals. */ public void setListening(boolean listening) { + if (mListening == listening) { + return; + } mListening = listening; if (listening) { mPhone.registerTelephonyCallback(mReceiverHandler::post, mTelephonyCallback); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index a57d849b24fa..25c6dce96b5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -38,6 +38,7 @@ import com.android.settingslib.graph.SignalDrawable; import com.android.systemui.DualToneHandler; import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; +import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; import java.util.ArrayList; @@ -64,6 +65,15 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, /** * Designated constructor + * + * This view is special, in that it is the only view in SystemUI that allows for a configuration + * override on a MCC/MNC-basis. This means that for every mobile view inflated, we have to + * construct a context with that override, since the resource system doesn't have a way to + * handle this for us. + * + * @param context A context with resources configured by MCC/MNC + * @param slot The string key defining which slot this icon refers to. Always "mobile" for the + * mobile icon */ public static StatusBarMobileView fromContext( Context context, 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 new file mode 100644 index 000000000000..a02dd3490341 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt @@ -0,0 +1,137 @@ +/* + * 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.ui + +import android.content.Context +import android.content.res.Configuration +import android.os.Bundle +import android.telephony.SubscriptionInfo +import android.view.ContextThemeWrapper +import com.android.systemui.Dumpable +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.demomode.DemoMode +import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK +import com.android.systemui.demomode.DemoModeController +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.connectivity.NetworkController +import com.android.systemui.statusbar.connectivity.SignalCallback +import java.io.PrintWriter +import javax.inject.Inject + +/** + * Every subscriptionId can have its own CarrierConfig associated with it, so we have to create our + * 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) + */ +@SysUISingleton +class MobileContextProvider +@Inject +constructor( + networkController: NetworkController, + dumpManager: DumpManager, + private val demoModeController: DemoModeController, +) : Dumpable, DemoMode { + private val subscriptions = mutableMapOf<Int, SubscriptionInfo>() + private val signalCallback = + object : SignalCallback { + override fun setSubs(subs: List<SubscriptionInfo>) { + subscriptions.clear() + subs.forEach { info -> subscriptions[info.subscriptionId] = info } + } + } + + // These should always be null when not in demo mode + private var demoMcc: Int? = null + private var demoMnc: Int? = null + + init { + networkController.addCallback(signalCallback) + dumpManager.registerDumpable(this) + demoModeController.addCallback(this) + } + + /** + * @return a context with the MCC/MNC [Configuration] values corresponding to this + * subscriptionId + */ + fun getMobileContextForSub(subId: Int, context: Context): Context { + if (demoModeController.isInDemoMode) { + return createMobileContextForDemoMode(context) + } + + // Fail back to the given context if no sub exists + val info = subscriptions[subId] ?: return context + + return createCarrierConfigContext(context, info.mcc, info.mnc) + } + + /** For Demo mode (for now), just apply the same MCC/MNC override for all subIds */ + private fun createMobileContextForDemoMode(context: Context): Context { + return createCarrierConfigContext(context, demoMcc ?: 0, demoMnc ?: 0) + } + + override fun dump(pw: PrintWriter, args: Array<out String>) { + pw.println( + "Subscriptions below will be inflated with a configuration context with " + + "MCC/MNC overrides" + ) + subscriptions.forEach { (subId, info) -> + pw.println(" Subscription with subId($subId) with MCC/MNC(${info.mcc}/${info.mnc})") + } + pw.println(" MCC override: ${demoMcc ?: "(none)"}") + pw.println(" MNC override: ${demoMnc ?: "(none)"}") + } + + override fun demoCommands(): List<String> { + return listOf(COMMAND_NETWORK) + } + + override fun onDemoModeFinished() { + demoMcc = null + demoMnc = null + } + + override fun dispatchDemoCommand(command: String, args: Bundle) { + val mccmnc = args.getString("mccmnc") ?: return + // Only length 5/6 strings are valid + if (!(mccmnc.length == 5 || mccmnc.length == 6)) { + return + } + + // MCC is always the first 3 digits, and mnc is the last 2 or 3 + demoMcc = mccmnc.subSequence(0, 3).toString().toInt() + demoMnc = mccmnc.subSequence(3, mccmnc.length).toString().toInt() + } + + companion object { + /** + * Creates a context based on this [SubscriptionInfo]'s MCC/MNC values, allowing the overlay + * system to properly load different carrier's iconography + */ + private fun createCarrierConfigContext(context: Context, mcc: Int, mnc: Int): Context { + // Copy the existing configuration + val c = Configuration(context.resources.configuration) + c.mcc = mcc + c.mnc = mnc + + return ContextThemeWrapper(context, context.theme).also { ctx -> + ctx.applyOverrideConfiguration(c) + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java index deb6150f773b..1169d3f21e28 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import android.content.Context; +import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.drawable.Icon; import android.os.Bundle; @@ -29,13 +31,13 @@ import android.widget.LinearLayout; import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.R; import com.android.systemui.demomode.DemoMode; -import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarMobileView; import com.android.systemui.statusbar.StatusBarWifiView; import com.android.systemui.statusbar.StatusIconDisplayable; +import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState; @@ -49,7 +51,6 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da private final LinearLayout mStatusIcons; private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>(); private final int mIconSize; - private final FeatureFlags mFeatureFlags; private StatusBarWifiView mWifiView; private boolean mDemoMode; @@ -57,14 +58,12 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da public DemoStatusIcons( LinearLayout statusIcons, - int iconSize, - FeatureFlags featureFlags + int iconSize ) { super(statusIcons.getContext()); mStatusIcons = statusIcons; mIconSize = iconSize; mColor = DarkIconDispatcher.DEFAULT_ICON_TINT; - mFeatureFlags = featureFlags; if (statusIcons instanceof StatusIconContainer) { setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons()); @@ -253,9 +252,13 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da } } - public void addMobileView(MobileIconState state) { + /** + * Add a new mobile icon view + */ + public void addMobileView(MobileIconState state, Context mobileContext) { Log.d(TAG, "addMobileView: "); - StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, state.slot); + StatusBarMobileView view = StatusBarMobileView + .fromContext(mobileContext, state.slot); view.applyMobileState(state); view.setStaticDrawableColor(mColor); @@ -265,19 +268,24 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da addView(view, getChildCount(), createLayoutParams()); } - public void updateMobileState(MobileIconState state) { - Log.d(TAG, "updateMobileState: "); - // If the view for this subId exists already, use it + /** + * Apply an update to a mobile icon view for the given {@link MobileIconState}. For + * compatibility with {@link MobileContextProvider}, we have to recreate the view every time we + * update it, since the context (and thus the {@link Configuration}) may have changed + */ + public void updateMobileState(MobileIconState state, Context mobileContext) { + Log.d(TAG, "updateMobileState: " + state); + + // The mobile config provided by MobileContextProvider could have changed; always recreate for (int i = 0; i < mMobileViews.size(); i++) { StatusBarMobileView view = mMobileViews.get(i); if (view.getState().subId == state.subId) { - view.applyMobileState(state); - return; + removeView(view); } } - // Else we have to add it - addMobileView(state); + // Add the replacement or new icon + addMobileView(state, mobileContext); } public void onRemoveIcon(StatusIconDisplayable view) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 8273d5737c2f..bd99713e3a69 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -36,7 +36,6 @@ import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.demomode.DemoModeCommandReceiver; -import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.BaseStatusBarWifiView; @@ -44,6 +43,7 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarMobileView; import com.android.systemui.statusbar.StatusBarWifiView; import com.android.systemui.statusbar.StatusIconDisplayable; +import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState; @@ -70,6 +70,7 @@ public interface StatusBarIconController { void addIconGroup(IconManager iconManager); /** */ void removeIconGroup(IconManager iconManager); + /** Refresh the state of an IconManager by recreating the views */ void refreshIconGroup(IconManager iconManager); /** */ @@ -82,21 +83,25 @@ public interface StatusBarIconController { void setSignalIcon(String slot, WifiIconState state); /** */ void setMobileIcons(String slot, List<MobileIconState> states); + /** * Display the no calling & SMS icons. */ void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states); + /** * Display the no calling & SMS icons. */ void setNoCallingIcons(String slot, List<CallIndicatorIconState> states); + public void setIconVisibility(String slot, boolean b); /** * Sets the live region mode for the icon - * @see android.view.View#setAccessibilityLiveRegion(int) - * @param slot Icon slot to set region for + * + * @param slot Icon slot to set region for * @param accessibilityLiveRegion live region mode for the icon + * @see android.view.View#setAccessibilityLiveRegion(int) */ void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion); @@ -115,8 +120,8 @@ public interface StatusBarIconController { static ArraySet<String> getIconHideList(Context context, String hideListStr) { ArraySet<String> ret = new ArraySet<>(); String[] hideList = hideListStr == null - ? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude) - : hideListStr.split(","); + ? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude) + : hideListStr.split(","); for (String slot : hideList) { if (!TextUtils.isEmpty(slot)) { ret.add(slot); @@ -134,11 +139,14 @@ public interface StatusBarIconController { public DarkIconManager( LinearLayout linearLayout, - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider mobileContextProvider, DarkIconDispatcher darkIconDispatcher) { - super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider); + super(linearLayout, + statusBarPipelineFlags, + wifiViewModelProvider, + mobileContextProvider); mIconHPadding = mContext.getResources().getDimensionPixelSize( R.dimen.status_bar_icon_padding); mDarkIconDispatcher = darkIconDispatcher; @@ -195,41 +203,49 @@ public interface StatusBarIconController { @SysUISingleton public static class Factory { - private final FeatureFlags mFeatureFlags; private final StatusBarPipelineFlags mStatusBarPipelineFlags; private final Provider<WifiViewModel> mWifiViewModelProvider; + private final MobileContextProvider mMobileContextProvider; private final DarkIconDispatcher mDarkIconDispatcher; @Inject public Factory( - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider mobileContextProvider, DarkIconDispatcher darkIconDispatcher) { - mFeatureFlags = featureFlags; mStatusBarPipelineFlags = statusBarPipelineFlags; mWifiViewModelProvider = wifiViewModelProvider; + mMobileContextProvider = mobileContextProvider; mDarkIconDispatcher = darkIconDispatcher; } public DarkIconManager create(LinearLayout group) { return new DarkIconManager( - group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider, + group, + mStatusBarPipelineFlags, + mWifiViewModelProvider, + mMobileContextProvider, mDarkIconDispatcher); } } } - /** */ + /** + * + */ class TintedIconManager extends IconManager { private int mColor; public TintedIconManager( ViewGroup group, - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, - Provider<WifiViewModel> wifiViewModelProvider) { - super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider); + Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider mobileContextProvider) { + super(group, + statusBarPipelineFlags, + wifiViewModelProvider, + mobileContextProvider); } @Override @@ -261,23 +277,26 @@ public interface StatusBarIconController { @SysUISingleton public static class Factory { - private final FeatureFlags mFeatureFlags; private final StatusBarPipelineFlags mStatusBarPipelineFlags; private final Provider<WifiViewModel> mWifiViewModelProvider; + private final MobileContextProvider mMobileContextProvider; @Inject public Factory( - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, - Provider<WifiViewModel> wifiViewModelProvider) { - mFeatureFlags = featureFlags; + Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider mobileContextProvider) { mStatusBarPipelineFlags = statusBarPipelineFlags; mWifiViewModelProvider = wifiViewModelProvider; + mMobileContextProvider = mobileContextProvider; } public TintedIconManager create(ViewGroup group) { return new TintedIconManager( - group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider); + group, + mStatusBarPipelineFlags, + mWifiViewModelProvider, + mMobileContextProvider); } } } @@ -287,9 +306,9 @@ public interface StatusBarIconController { */ class IconManager implements DemoModeCommandReceiver { protected final ViewGroup mGroup; - private final FeatureFlags mFeatureFlags; private final StatusBarPipelineFlags mStatusBarPipelineFlags; private final Provider<WifiViewModel> mWifiViewModelProvider; + private final MobileContextProvider mMobileContextProvider; protected final Context mContext; protected final int mIconSize; // Whether or not these icons show up in dumpsys @@ -305,13 +324,13 @@ public interface StatusBarIconController { public IconManager( ViewGroup group, - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, - Provider<WifiViewModel> wifiViewModelProvider) { + Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider mobileContextProvider) { mGroup = group; - mFeatureFlags = featureFlags; mStatusBarPipelineFlags = statusBarPipelineFlags; mWifiViewModelProvider = wifiViewModelProvider; + mMobileContextProvider = mobileContextProvider; mContext = group.getContext(); mIconSize = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size); @@ -403,12 +422,15 @@ public interface StatusBarIconController { @VisibleForTesting protected StatusBarMobileView addMobileIcon(int index, String slot, MobileIconState state) { - StatusBarMobileView view = onCreateStatusBarMobileView(slot); + // Use the `subId` field as a key to query for the correct context + StatusBarMobileView view = onCreateStatusBarMobileView(state.subId, slot); view.applyMobileState(state); mGroup.addView(view, index, onCreateLayoutParams()); if (mIsInDemoMode) { - mDemoStatusIcons.addMobileView(state); + Context mobileContext = mMobileContextProvider + .getMobileContextForSub(state.subId, mContext); + mDemoStatusIcons.addMobileView(state, mobileContext); } return view; } @@ -427,8 +449,10 @@ public interface StatusBarIconController { mContext, slot, mWifiViewModelProvider.get()); } - private StatusBarMobileView onCreateStatusBarMobileView(String slot) { - StatusBarMobileView view = StatusBarMobileView.fromContext(mContext, slot); + private StatusBarMobileView onCreateStatusBarMobileView(int subId, String slot) { + Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext); + StatusBarMobileView view = StatusBarMobileView + .fromContext(mobileContext, slot); return view; } @@ -516,7 +540,9 @@ public interface StatusBarIconController { } if (mIsInDemoMode) { - mDemoStatusIcons.updateMobileState(state); + Context mobileContext = mMobileContextProvider + .getMobileContextForSub(state.subId, mContext); + mDemoStatusIcons.updateMobileState(state, mobileContext); } } @@ -553,7 +579,7 @@ public interface StatusBarIconController { } protected DemoStatusIcons createDemoStatusIcons() { - return new DemoStatusIcons((LinearLayout) mGroup, mIconSize, mFeatureFlags); + return new DemoStatusIcons((LinearLayout) mGroup, mIconSize); } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt new file mode 100644 index 000000000000..0fdda62e3b30 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProviderTest.kt @@ -0,0 +1,122 @@ +/* + * 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.ui + +import android.telephony.SubscriptionInfo +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.demomode.DemoModeController +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.connectivity.NetworkController +import com.android.systemui.statusbar.connectivity.SignalCallback +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.withArgCaptor +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@SmallTest +class MobileContextProviderTest : SysuiTestCase() { + @Mock private lateinit var networkController: NetworkController + @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var demoModeController: DemoModeController + + private lateinit var provider: MobileContextProvider + private lateinit var signalCallback: SignalCallback + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + provider = + MobileContextProvider( + networkController, + dumpManager, + demoModeController, + ) + + signalCallback = withArgCaptor { verify(networkController).addCallback(capture()) } + } + + @Test + fun test_oneSubscription_contextHasMccMnc() { + // GIVEN there is one SubscriptionInfo + signalCallback.setSubs(listOf(SUB_1)) + + // WHEN we ask for a mobile context + val ctx = provider.getMobileContextForSub(SUB_1_ID, context) + + // THEN the configuration of that context reflect this subscription's MCC/MNC override + val config = ctx.resources.configuration + assertThat(config.mcc).isEqualTo(SUB_1_MCC) + assertThat(config.mnc).isEqualTo(SUB_1_MNC) + } + + @Test + fun test_twoSubscriptions_eachContextReflectsMccMnc() { + // GIVEN there are two SubscriptionInfos + signalCallback.setSubs(listOf(SUB_1, SUB_2)) + + // WHEN we ask for a mobile context for each sub + val ctx1 = provider.getMobileContextForSub(SUB_1_ID, context) + val ctx2 = provider.getMobileContextForSub(SUB_2_ID, context) + + // THEN the configuration of each context reflect this subscription's MCC/MNC override + val config1 = ctx1.resources.configuration + assertThat(config1.mcc).isEqualTo(SUB_1_MCC) + assertThat(config1.mnc).isEqualTo(SUB_1_MNC) + + val config2 = ctx2.resources.configuration + assertThat(config2.mcc).isEqualTo(SUB_2_MCC) + assertThat(config2.mnc).isEqualTo(SUB_2_MNC) + } + + @Test + fun test_requestingContextForNonexistentSubscription_returnsGivenContext() { + // GIVEN no SubscriptionInfos + signalCallback.setSubs(listOf()) + + // WHEN we ask for a mobile context for an unknown subscription + val ctx = provider.getMobileContextForSub(SUB_1_ID, context) + + // THEN we get the original context back + assertThat(ctx).isEqualTo(context) + } + + private val SUB_1_ID = 1 + private val SUB_1_MCC = 123 + private val SUB_1_MNC = 456 + private val SUB_1 = + mock<SubscriptionInfo>().also { + whenever(it.subscriptionId).thenReturn(SUB_1_ID) + whenever(it.mcc).thenReturn(SUB_1_MCC) + whenever(it.mnc).thenReturn(SUB_1_MNC) + } + + private val SUB_2_ID = 2 + private val SUB_2_MCC = 666 + private val SUB_2_MNC = 777 + private val SUB_2 = + mock<SubscriptionInfo>().also { + whenever(it.subscriptionId).thenReturn(SUB_2_ID) + whenever(it.mcc).thenReturn(SUB_2_MCC) + whenever(it.mnc).thenReturn(SUB_2_MNC) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java index ca98143044c1..de7db74495af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java @@ -20,7 +20,10 @@ import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -30,12 +33,12 @@ import android.widget.LinearLayout; import androidx.test.filters.SmallTest; import com.android.internal.statusbar.StatusBarIcon; -import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarMobileView; import com.android.systemui.statusbar.StatusBarWifiView; import com.android.systemui.statusbar.StatusIconDisplayable; +import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider; import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager; import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; @@ -55,15 +58,19 @@ import javax.inject.Provider; @SmallTest public class StatusBarIconControllerTest extends LeakCheckedTest { + private MobileContextProvider mMobileContextProvider = mock(MobileContextProvider.class); + @Before public void setup() { injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); + // For testing, ignore context overrides + when(mMobileContextProvider.getMobileContextForSub(anyInt(), any())).thenReturn(mContext); } @Test public void testSetCalledOnAdd_IconManager() { LinearLayout layout = new LinearLayout(mContext); - TestIconManager manager = new TestIconManager(layout); + TestIconManager manager = new TestIconManager(layout, mMobileContextProvider); testCallOnAdd_forManager(manager); } @@ -72,9 +79,9 @@ public class StatusBarIconControllerTest extends LeakCheckedTest { LinearLayout layout = new LinearLayout(mContext); TestDarkIconManager manager = new TestDarkIconManager( layout, - mock(FeatureFlags.class), mock(StatusBarPipelineFlags.class), () -> mock(WifiViewModel.class), + mMobileContextProvider, mock(DarkIconDispatcher.class)); testCallOnAdd_forManager(manager); } @@ -114,11 +121,14 @@ public class StatusBarIconControllerTest extends LeakCheckedTest { TestDarkIconManager( LinearLayout group, - FeatureFlags featureFlags, StatusBarPipelineFlags statusBarPipelineFlags, Provider<WifiViewModel> wifiViewModelProvider, + MobileContextProvider contextProvider, DarkIconDispatcher darkIconDispatcher) { - super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider, + super(group, + statusBarPipelineFlags, + wifiViewModelProvider, + contextProvider, darkIconDispatcher); } @@ -153,11 +163,11 @@ public class StatusBarIconControllerTest extends LeakCheckedTest { } private static class TestIconManager extends IconManager implements TestableIconManager { - TestIconManager(ViewGroup group) { + TestIconManager(ViewGroup group, MobileContextProvider contextProvider) { super(group, - mock(FeatureFlags.class), mock(StatusBarPipelineFlags.class), - () -> mock(WifiViewModel.class)); + () -> mock(WifiViewModel.class), + contextProvider); } @Override |