Loading packages/SystemUI/res/layout/qs_carrier_group.xml +11 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,17 @@ android:orientation="horizontal"> <com.android.systemui.util.AutoMarqueeTextView android:id="@+id/no_carrier_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.QS.Status" android:textDirection="locale" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:maxEms="7" android:visibility="gone"/> <include layout="@layout/qs_carrier" android:id="@+id/carrier1" Loading packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +3 −1 Original line number Diff line number Diff line Loading @@ -362,7 +362,9 @@ public class CarrierTextController { } } } if (allSimsMissing) { // Only create "No SIM card" if no cards with CarrierName && no wifi when some sim is READY // This condition will also be true always when numSubs == 0 if (allSimsMissing && !anySimReadyAndInService) { if (numSubs != 0) { // Shows "No SIM card | Emergency calls only" on devices that are voice-capable. // This depends on mPlmn containing the text "Emergency calls only" when the radio Loading packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java +41 −39 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.VisibleForTesting; Loading Loading @@ -54,6 +55,7 @@ public class QSCarrierGroup extends LinearLayout implements private View[] mCarrierDividers = new View[SIM_SLOTS - 1]; private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS]; private TextView mNoSimTextView; private final CellSignalState[] mInfos = new CellSignalState[SIM_SLOTS]; private CarrierTextController mCarrierTextController; private ActivityStarter mActivityStarter; Loading Loading @@ -93,10 +95,13 @@ public class QSCarrierGroup extends LinearLayout implements mCarrierDividers[0] = findViewById(R.id.qs_carrier_divider1); mCarrierDividers[1] = findViewById(R.id.qs_carrier_divider2); mNoSimTextView = findViewById(R.id.no_carrier_text); for (int i = 0; i < SIM_SLOTS; i++) { mInfos[i] = new CellSignalState(); mCarrierGroups[i].setOnClickListener(this); } mNoSimTextView.setOnClickListener(this); CharSequence separator = mContext.getString( com.android.internal.R.string.kg_text_message_separator); Loading Loading @@ -153,11 +158,8 @@ public class QSCarrierGroup extends LinearLayout implements @Override public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { if (info.airplaneMode) { setVisibility(View.GONE); } else { setVisibility(View.VISIBLE); if (info.anySimReady) { mNoSimTextView.setVisibility(View.GONE); if (!info.airplaneMode && info.anySimReady) { boolean[] slotSeen = new boolean[SIM_SLOTS]; if (info.listOfCarriers.length == info.subscriptionIds.length) { for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { Loading Loading @@ -188,15 +190,15 @@ public class QSCarrierGroup extends LinearLayout implements Log.e(TAG, "Carrier information arrays not of same length"); } } else { mInfos[0].visible = false; mCarrierGroups[0].setCarrierText(info.carrierText); mCarrierGroups[0].setVisibility(View.VISIBLE); for (int i = 1; i < SIM_SLOTS; i++) { // No sims or airplane mode (but not WFC). Do not show QSCarrierGroup, instead just show // info.carrierText in a different view. for (int i = 0; i < SIM_SLOTS; i++) { mInfos[i].visible = false; mCarrierGroups[i].setCarrierText(""); mCarrierGroups[i].setVisibility(View.GONE); } } mNoSimTextView.setText(info.carrierText); mNoSimTextView.setVisibility(View.VISIBLE); } handleUpdateState(); } Loading packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java +68 −0 Original line number Diff line number Diff line Loading @@ -22,11 +22,14 @@ import static android.telephony.SubscriptionManager.DATA_ROAMING_ENABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; 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.reset; import static org.mockito.Mockito.verify; Loading @@ -34,15 +37,18 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.text.TextUtils; import com.android.internal.telephony.IccCardConstants; import com.android.systemui.Dependency; Loading Loading @@ -81,6 +87,9 @@ public class CarrierTextControllerTest extends SysuiTestCase { TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID, TEST_CARRIER_ID, 0); private static final SubscriptionInfo TEST_SUBSCRIPTION_NULL = new SubscriptionInfo(0, "", 0, TEST_CARRIER, null, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_DISABLE, null, null, null, null, false, null, ""); private static final SubscriptionInfo TEST_SUBSCRIPTION_ROAMING = new SubscriptionInfo(0, "", 0, TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_ENABLE, null, null, null, null, false, null, ""); Loading Loading @@ -285,6 +294,65 @@ public class CarrierTextControllerTest extends SysuiTestCase { assertEquals(1, info.subscriptionIds.length); } @Test public void testCarrierText_noTextOnReadySimWhenNull() { reset(mCarrierTextCallback); List<SubscriptionInfo> list = new ArrayList<>(); list.add(TEST_SUBSCRIPTION_NULL); when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY); when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list); mKeyguardUpdateMonitor.mServiceStates = new HashMap<>(); ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor = ArgumentCaptor.forClass( CarrierTextController.CarrierTextCallbackInfo.class); mCarrierTextController.updateCarrierText(); mTestableLooper.processAllMessages(); verify(mCarrierTextCallback).updateCarrierInfo(captor.capture()); assertTrue("Carrier text should be empty, instead it's " + captor.getValue().carrierText, TextUtils.isEmpty(captor.getValue().carrierText)); assertFalse("No SIM should be available", captor.getValue().anySimReady); } @Test public void testCarrierText_noTextOnReadySimWhenNull_airplaneMode_wifiOn() { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1); reset(mCarrierTextCallback); List<SubscriptionInfo> list = new ArrayList<>(); list.add(TEST_SUBSCRIPTION_NULL); when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY); when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list); mockWifi(); mKeyguardUpdateMonitor.mServiceStates = new HashMap<>(); ServiceState ss = mock(ServiceState.class); when(ss.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE); mKeyguardUpdateMonitor.mServiceStates.put(TEST_SUBSCRIPTION_NULL.getSubscriptionId(), ss); ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor = ArgumentCaptor.forClass( CarrierTextController.CarrierTextCallbackInfo.class); mCarrierTextController.updateCarrierText(); mTestableLooper.processAllMessages(); verify(mCarrierTextCallback).updateCarrierInfo(captor.capture()); assertFalse("No SIM should be available", captor.getValue().anySimReady); // There's no airplane mode if at least one SIM is State.READY and there's wifi assertFalse("Device should not be in airplane mode", captor.getValue().airplaneMode); assertNotEquals(AIRPLANE_MODE_TEXT, captor.getValue().carrierText); } private void mockWifi() { when(mWifiManager.isWifiEnabled()).thenReturn(true); WifiInfo wifiInfo = mock(WifiInfo.class); when(wifiInfo.getBSSID()).thenReturn(""); when(mWifiManager.getConnectionInfo()).thenReturn(wifiInfo); } @Test public void testCreateInfo_noSubscriptions() { reset(mCarrierTextCallback); Loading Loading
packages/SystemUI/res/layout/qs_carrier_group.xml +11 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,17 @@ android:orientation="horizontal"> <com.android.systemui.util.AutoMarqueeTextView android:id="@+id/no_carrier_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.QS.Status" android:textDirection="locale" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:maxEms="7" android:visibility="gone"/> <include layout="@layout/qs_carrier" android:id="@+id/carrier1" Loading
packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +3 −1 Original line number Diff line number Diff line Loading @@ -362,7 +362,9 @@ public class CarrierTextController { } } } if (allSimsMissing) { // Only create "No SIM card" if no cards with CarrierName && no wifi when some sim is READY // This condition will also be true always when numSubs == 0 if (allSimsMissing && !anySimReadyAndInService) { if (numSubs != 0) { // Shows "No SIM card | Emergency calls only" on devices that are voice-capable. // This depends on mPlmn containing the text "Emergency calls only" when the radio Loading
packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java +41 −39 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.VisibleForTesting; Loading Loading @@ -54,6 +55,7 @@ public class QSCarrierGroup extends LinearLayout implements private View[] mCarrierDividers = new View[SIM_SLOTS - 1]; private QSCarrier[] mCarrierGroups = new QSCarrier[SIM_SLOTS]; private TextView mNoSimTextView; private final CellSignalState[] mInfos = new CellSignalState[SIM_SLOTS]; private CarrierTextController mCarrierTextController; private ActivityStarter mActivityStarter; Loading Loading @@ -93,10 +95,13 @@ public class QSCarrierGroup extends LinearLayout implements mCarrierDividers[0] = findViewById(R.id.qs_carrier_divider1); mCarrierDividers[1] = findViewById(R.id.qs_carrier_divider2); mNoSimTextView = findViewById(R.id.no_carrier_text); for (int i = 0; i < SIM_SLOTS; i++) { mInfos[i] = new CellSignalState(); mCarrierGroups[i].setOnClickListener(this); } mNoSimTextView.setOnClickListener(this); CharSequence separator = mContext.getString( com.android.internal.R.string.kg_text_message_separator); Loading Loading @@ -153,11 +158,8 @@ public class QSCarrierGroup extends LinearLayout implements @Override public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { if (info.airplaneMode) { setVisibility(View.GONE); } else { setVisibility(View.VISIBLE); if (info.anySimReady) { mNoSimTextView.setVisibility(View.GONE); if (!info.airplaneMode && info.anySimReady) { boolean[] slotSeen = new boolean[SIM_SLOTS]; if (info.listOfCarriers.length == info.subscriptionIds.length) { for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { Loading Loading @@ -188,15 +190,15 @@ public class QSCarrierGroup extends LinearLayout implements Log.e(TAG, "Carrier information arrays not of same length"); } } else { mInfos[0].visible = false; mCarrierGroups[0].setCarrierText(info.carrierText); mCarrierGroups[0].setVisibility(View.VISIBLE); for (int i = 1; i < SIM_SLOTS; i++) { // No sims or airplane mode (but not WFC). Do not show QSCarrierGroup, instead just show // info.carrierText in a different view. for (int i = 0; i < SIM_SLOTS; i++) { mInfos[i].visible = false; mCarrierGroups[i].setCarrierText(""); mCarrierGroups[i].setVisibility(View.GONE); } } mNoSimTextView.setText(info.carrierText); mNoSimTextView.setVisibility(View.VISIBLE); } handleUpdateState(); } Loading
packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java +68 −0 Original line number Diff line number Diff line Loading @@ -22,11 +22,14 @@ import static android.telephony.SubscriptionManager.DATA_ROAMING_ENABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; 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.reset; import static org.mockito.Mockito.verify; Loading @@ -34,15 +37,18 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.net.ConnectivityManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.text.TextUtils; import com.android.internal.telephony.IccCardConstants; import com.android.systemui.Dependency; Loading Loading @@ -81,6 +87,9 @@ public class CarrierTextControllerTest extends SysuiTestCase { TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID, TEST_CARRIER_ID, 0); private static final SubscriptionInfo TEST_SUBSCRIPTION_NULL = new SubscriptionInfo(0, "", 0, TEST_CARRIER, null, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_DISABLE, null, null, null, null, false, null, ""); private static final SubscriptionInfo TEST_SUBSCRIPTION_ROAMING = new SubscriptionInfo(0, "", 0, TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_ENABLE, null, null, null, null, false, null, ""); Loading Loading @@ -285,6 +294,65 @@ public class CarrierTextControllerTest extends SysuiTestCase { assertEquals(1, info.subscriptionIds.length); } @Test public void testCarrierText_noTextOnReadySimWhenNull() { reset(mCarrierTextCallback); List<SubscriptionInfo> list = new ArrayList<>(); list.add(TEST_SUBSCRIPTION_NULL); when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY); when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list); mKeyguardUpdateMonitor.mServiceStates = new HashMap<>(); ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor = ArgumentCaptor.forClass( CarrierTextController.CarrierTextCallbackInfo.class); mCarrierTextController.updateCarrierText(); mTestableLooper.processAllMessages(); verify(mCarrierTextCallback).updateCarrierInfo(captor.capture()); assertTrue("Carrier text should be empty, instead it's " + captor.getValue().carrierText, TextUtils.isEmpty(captor.getValue().carrierText)); assertFalse("No SIM should be available", captor.getValue().anySimReady); } @Test public void testCarrierText_noTextOnReadySimWhenNull_airplaneMode_wifiOn() { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1); reset(mCarrierTextCallback); List<SubscriptionInfo> list = new ArrayList<>(); list.add(TEST_SUBSCRIPTION_NULL); when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY); when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list); mockWifi(); mKeyguardUpdateMonitor.mServiceStates = new HashMap<>(); ServiceState ss = mock(ServiceState.class); when(ss.getDataRegState()).thenReturn(ServiceState.STATE_IN_SERVICE); mKeyguardUpdateMonitor.mServiceStates.put(TEST_SUBSCRIPTION_NULL.getSubscriptionId(), ss); ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor = ArgumentCaptor.forClass( CarrierTextController.CarrierTextCallbackInfo.class); mCarrierTextController.updateCarrierText(); mTestableLooper.processAllMessages(); verify(mCarrierTextCallback).updateCarrierInfo(captor.capture()); assertFalse("No SIM should be available", captor.getValue().anySimReady); // There's no airplane mode if at least one SIM is State.READY and there's wifi assertFalse("Device should not be in airplane mode", captor.getValue().airplaneMode); assertNotEquals(AIRPLANE_MODE_TEXT, captor.getValue().carrierText); } private void mockWifi() { when(mWifiManager.isWifiEnabled()).thenReturn(true); WifiInfo wifiInfo = mock(WifiInfo.class); when(wifiInfo.getBSSID()).thenReturn(""); when(mWifiManager.getConnectionInfo()).thenReturn(wifiInfo); } @Test public void testCreateInfo_noSubscriptions() { reset(mCarrierTextCallback); Loading