diff options
3 files changed, 195 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 2ce69650b65c..d5bd2b202803 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -21,12 +21,15 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; +import android.os.Handler; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.WirelessUtils; @@ -206,6 +209,7 @@ public class CarrierTextController { protected void updateCarrierText() { boolean allSimsMissing = true; boolean anySimReadyAndInService = false; + boolean missingSimsWithSubs = false; CharSequence displayText = null; List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); @@ -252,6 +256,7 @@ public class CarrierTextController { // described above. displayText = makeCarrierStringOnEmergencyCapable( getMissingSimMessage(), subs.get(0).getCarrierName()); + missingSimsWithSubs = true; } else { // We don't have a SubscriptionInfo to get the emergency calls only from. // Grab it from the old sticky broadcast if possible instead. We can use it @@ -288,12 +293,14 @@ public class CarrierTextController { displayText = getAirplaneModeMessage(); } + Handler handler = Dependency.get(Dependency.MAIN_HANDLER); + final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo( + displayText, + displayText.toString().split(mSeparator.toString()), + anySimReadyAndInService && !missingSimsWithSubs, + subsIds); if (mCarrierTextCallback != null) { - mCarrierTextCallback.updateCarrierInfo(new CarrierTextCallbackInfo( - displayText, - displayText.toString().split(mSeparator.toString()), - anySimReadyAndInService, - subsIds)); + handler.post(() -> mCarrierTextCallback.updateCarrierInfo(info)); } } @@ -487,7 +494,8 @@ public class CarrierTextController { public final boolean anySimReady; public final int[] subscriptionIds; - CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers, + @VisibleForTesting + public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers, boolean anySimReady, int[] subscriptionIds) { this.carrierText = carrierText; this.listOfCarriers = listOfCarriers; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index c0ed4b97eaff..b865ce8d261a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -54,6 +54,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.Utils; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.graph.SignalDrawable; +import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R.dimen; import com.android.systemui.plugins.ActivityStarter; @@ -134,6 +135,15 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mDeviceProvisionedController = deviceProvisionedController; } + @VisibleForTesting + public QSFooterImpl(Context context, AttributeSet attrs) { + this(context, attrs, + Dependency.get(ActivityStarter.class), + Dependency.get(UserInfoController.class), + Dependency.get(NetworkController.class), + Dependency.get(DeviceProvisionedController.class)); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -476,32 +486,62 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mInfos[0].visible && mInfos[1].visible ? View.VISIBLE : View.GONE); } + @VisibleForTesting + protected int getSlotIndex(int subscriptionId) { + return SubscriptionManager.getSlotIndex(subscriptionId); + } + @Override public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { if (info.anySimReady) { boolean[] slotSeen = new boolean[SIM_SLOTS]; - for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { - int slot = SubscriptionManager.getSlotIndex(info.subscriptionIds[i]); - mInfos[slot].visible = true; - slotSeen[slot] = true; - mCarrierTexts[slot].setText(info.listOfCarriers[i].toString().trim()); - mCarrierGroups[slot].setVisibility(View.VISIBLE); - } - for (int i = 0; i < SIM_SLOTS; i++) { - if (!slotSeen[i]) { + if (info.listOfCarriers.length == info.subscriptionIds.length) { + for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { + int slot = getSlotIndex(info.subscriptionIds[i]); + if (slot >= SIM_SLOTS) { + Log.w(TAG, "updateInfoCarrier - slot: " + slot); + continue; + } + if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, + "Invalid SIM slot index for subscription: " + + info.subscriptionIds[i]); + continue; + } + mInfos[slot].visible = true; + slotSeen[slot] = true; + mCarrierTexts[slot].setText(info.listOfCarriers[i].toString().trim()); + mCarrierGroups[slot].setVisibility(View.VISIBLE); + } + for (int i = 0; i < SIM_SLOTS; i++) { + if (!slotSeen[i]) { + mInfos[i].visible = false; + mCarrierGroups[i].setVisibility(View.GONE); + } + } + } else { + // If there are sims ready but there are not the same number of carrier names as + // subscription ids, just show the full text in the first slot + mInfos[0].visible = true; + mCarrierTexts[0].setText(info.carrierText); + mCarrierGroups[0].setVisibility(View.VISIBLE); + for (int i = 1; i < SIM_SLOTS; i++) { mInfos[i].visible = false; + mCarrierTexts[i].setText(""); mCarrierGroups[i].setVisibility(View.GONE); } } - handleUpdateState(); } else { mInfos[0].visible = false; - mInfos[1].visible = false; mCarrierTexts[0].setText(info.carrierText); mCarrierGroups[0].setVisibility(View.VISIBLE); - mCarrierGroups[1].setVisibility(View.GONE); - handleUpdateState(); + for (int i = 1; i < SIM_SLOTS; i++) { + mInfos[i].visible = false; + mCarrierTexts[i].setText(""); + mCarrierGroups[i].setVisibility(View.GONE); + } } + handleUpdateState(); } @Override @@ -510,9 +550,14 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming) { - int slotIndex = SubscriptionManager.getSlotIndex(subId); + int slotIndex = getSlotIndex(subId); if (slotIndex >= SIM_SLOTS) { - Log.e(TAG, "setMobileDataIndicators - slot: " + slotIndex); + Log.w(TAG, "setMobileDataIndicators - slot: " + slotIndex); + return; + } + if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + Log.e(TAG, "Invalid SIM slot index for subscription: " + subId); + return; } mInfos[slotIndex].visible = statusIcon.visible; mInfos[slotIndex].mobileSignalIconId = statusIcon.icon; @@ -539,7 +584,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, boolean roaming; } - /** * TextView that changes its ellipsize value with its visibility. */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java index 850396299ae5..374a73c1d451 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java @@ -16,27 +16,35 @@ package com.android.systemui.qs; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.support.test.filters.SmallTest; +import android.telephony.SubscriptionManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; import android.view.View; +import com.android.keyguard.CarrierTextController.CarrierTextCallbackInfo; import com.android.systemui.R; import com.android.systemui.R.id; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; @RunWith(AndroidTestingRunner.class) @RunWithLooper @@ -68,4 +76,117 @@ public class QSFooterImplTest extends LeakCheckedTest { // Verify Settings wasn't launched. verify(mActivityStarter, never()).startActivity(any(), anyBoolean()); } + + @Test // throws no Exception + public void testUpdateCarrierText_sameLengts() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenAnswer( + new Answer<Integer>() { + @Override + public Integer answer(InvocationOnMock invocationOnMock) throws Throwable { + return invocationOnMock.getArgument(0); + } + }); + + // listOfCarriers length 1, subscriptionIds length 1, anySims false + CarrierTextCallbackInfo c1 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + false, + new int[]{0}); + spiedFooter.updateCarrierInfo(c1); + + // listOfCarriers length 1, subscriptionIds length 1, anySims true + CarrierTextCallbackInfo c2 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + true, + new int[]{0}); + spiedFooter.updateCarrierInfo(c2); + + // listOfCarriers length 2, subscriptionIds length 2, anySims false + CarrierTextCallbackInfo c3 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + false, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c3); + + // listOfCarriers length 2, subscriptionIds length 2, anySims true + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testUpdateCarrierText_differentLength() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenAnswer( + new Answer<Integer>() { + @Override + public Integer answer(InvocationOnMock invocationOnMock) throws Throwable { + return invocationOnMock.getArgument(0); + } + }); + + // listOfCarriers length 2, subscriptionIds length 1, anySims false + CarrierTextCallbackInfo c1 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + false, + new int[]{0}); + spiedFooter.updateCarrierInfo(c1); + + // listOfCarriers length 2, subscriptionIds length 1, anySims true + CarrierTextCallbackInfo c2 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0}); + spiedFooter.updateCarrierInfo(c2); + + // listOfCarriers length 1, subscriptionIds length 2, anySims false + CarrierTextCallbackInfo c3 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + false, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c3); + + // listOfCarriers length 1, subscriptionIds length 2, anySims true + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testUpdateCarrierText_invalidSim() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenReturn( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + CarrierTextCallbackInfo c4 = new CarrierTextCallbackInfo( + "", + new CharSequence[]{"", ""}, + true, + new int[]{0, 1}); + spiedFooter.updateCarrierInfo(c4); + } + + @Test // throws no Exception + public void testSetMobileDataIndicators_invalidSim() { + QSFooterImpl spiedFooter = Mockito.spy(mFooter); + when(spiedFooter.getSlotIndex(anyInt())).thenReturn( + SubscriptionManager.INVALID_SIM_SLOT_INDEX); + spiedFooter.setMobileDataIndicators( + mock(NetworkController.IconState.class), + mock(NetworkController.IconState.class), + 0, 0, true, true, "", "", true, 0, true); + } + } |