Merge "Refactor CarrierTextController"
This commit is contained in:
committed by
Android (Google) Code Review
commit
1d55fb2fd4
@@ -52,9 +52,11 @@ public class CarrierTextController {
|
||||
private boolean mTelephonyCapable;
|
||||
private boolean mShowMissingSim;
|
||||
private boolean mShowAirplaneMode;
|
||||
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@VisibleForTesting
|
||||
protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private WifiManager mWifiManager;
|
||||
private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()];
|
||||
private boolean[] mSimErrorState;
|
||||
private final int mSimSlotsNumber;
|
||||
private CarrierTextCallback mCarrierTextCallback;
|
||||
private Context mContext;
|
||||
private CharSequence mSeparator;
|
||||
@@ -72,7 +74,8 @@ public class CarrierTextController {
|
||||
}
|
||||
};
|
||||
|
||||
private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
|
||||
@VisibleForTesting
|
||||
protected final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
|
||||
@Override
|
||||
public void onRefreshCarrierInfo() {
|
||||
if (DEBUG) {
|
||||
@@ -93,7 +96,7 @@ public class CarrierTextController {
|
||||
}
|
||||
|
||||
public void onSimStateChanged(int subId, int slotId, IccCardConstants.State simState) {
|
||||
if (slotId < 0) {
|
||||
if (slotId < 0 || slotId >= mSimSlotsNumber) {
|
||||
Log.d(TAG, "onSimStateChanged() - slotId invalid: " + slotId
|
||||
+ " mTelephonyCapable: " + Boolean.toString(mTelephonyCapable));
|
||||
return;
|
||||
@@ -144,36 +147,48 @@ public class CarrierTextController {
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
mSeparator = separator;
|
||||
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
|
||||
mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
|
||||
Context.TELEPHONY_SERVICE)).getPhoneCount();
|
||||
mSimErrorState = new boolean[mSimSlotsNumber];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are faulty cards. Adds the text depending on the slot of the card
|
||||
*
|
||||
* @param text: current carrier text based on the sim state
|
||||
* @param carrierNames names order by subscription order
|
||||
* @param subOrderBySlot array containing the sub index for each slot ID
|
||||
* @param noSims: whether a valid sim card is inserted
|
||||
* @return text
|
||||
*/
|
||||
private CharSequence updateCarrierTextWithSimIoError(CharSequence text, boolean noSims) {
|
||||
private CharSequence updateCarrierTextWithSimIoError(CharSequence text,
|
||||
CharSequence[] carrierNames, int[] subOrderBySlot, boolean noSims) {
|
||||
final CharSequence carrier = "";
|
||||
CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
|
||||
IccCardConstants.State.CARD_IO_ERROR, carrier);
|
||||
// mSimErrorState has the state of each sim indexed by slotID.
|
||||
for (int index = 0; index < mSimErrorState.length; index++) {
|
||||
if (mSimErrorState[index]) {
|
||||
// In the case when no sim cards are detected but a faulty card is inserted
|
||||
// overwrite the text and only show "Invalid card"
|
||||
if (noSims) {
|
||||
return concatenate(carrierTextForSimIOError,
|
||||
getContext().getText(
|
||||
com.android.internal.R.string.emergency_calls_only),
|
||||
mSeparator);
|
||||
} else if (index == 0) {
|
||||
// prepend "Invalid card" when faulty card is inserted in slot 0
|
||||
text = concatenate(carrierTextForSimIOError, text, mSeparator);
|
||||
} else {
|
||||
// concatenate "Invalid card" when faulty card is inserted in slot 1
|
||||
text = concatenate(text, carrierTextForSimIOError, mSeparator);
|
||||
}
|
||||
if (!mSimErrorState[index]) {
|
||||
continue;
|
||||
}
|
||||
// In the case when no sim cards are detected but a faulty card is inserted
|
||||
// overwrite the text and only show "Invalid card"
|
||||
if (noSims) {
|
||||
return concatenate(carrierTextForSimIOError,
|
||||
getContext().getText(
|
||||
com.android.internal.R.string.emergency_calls_only),
|
||||
mSeparator);
|
||||
} else if (subOrderBySlot[index] != -1) {
|
||||
int subIndex = subOrderBySlot[index];
|
||||
// prepend "Invalid card" when faulty card is inserted in slot 0 or 1
|
||||
carrierNames[subIndex] = concatenate(carrierTextForSimIOError,
|
||||
carrierNames[subIndex],
|
||||
mSeparator);
|
||||
} else {
|
||||
// concatenate "Invalid card" when faulty card is inserted in other slot
|
||||
text = concatenate(text, carrierTextForSimIOError, mSeparator);
|
||||
}
|
||||
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -209,16 +224,25 @@ public class CarrierTextController {
|
||||
protected void updateCarrierText() {
|
||||
boolean allSimsMissing = true;
|
||||
boolean anySimReadyAndInService = false;
|
||||
boolean missingSimsWithSubs = false;
|
||||
CharSequence displayText = null;
|
||||
|
||||
List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
|
||||
final int numSubs = subs.size();
|
||||
final int[] subsIds = new int[numSubs];
|
||||
// This array will contain in position i, the index of subscription in slot ID i.
|
||||
// -1 if no subscription in that slot
|
||||
final int[] subOrderBySlot = new int[mSimSlotsNumber];
|
||||
for (int i = 0; i < mSimSlotsNumber; i++) {
|
||||
subOrderBySlot[i] = -1;
|
||||
}
|
||||
final CharSequence[] carrierNames = new CharSequence[numSubs];
|
||||
if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs);
|
||||
|
||||
for (int i = 0; i < numSubs; i++) {
|
||||
int subId = subs.get(i).getSubscriptionId();
|
||||
carrierNames[i] = "";
|
||||
subsIds[i] = subId;
|
||||
subOrderBySlot[subs.get(i).getSimSlotIndex()] = i;
|
||||
IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId);
|
||||
CharSequence carrierName = subs.get(i).getCarrierName();
|
||||
CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName);
|
||||
@@ -227,7 +251,7 @@ public class CarrierTextController {
|
||||
}
|
||||
if (carrierTextForSimState != null) {
|
||||
allSimsMissing = false;
|
||||
displayText = concatenate(displayText, carrierTextForSimState, mSeparator);
|
||||
carrierNames[i] = carrierTextForSimState;
|
||||
}
|
||||
if (simState == IccCardConstants.State.READY) {
|
||||
ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId);
|
||||
@@ -256,7 +280,6 @@ 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
|
||||
@@ -286,24 +309,32 @@ public class CarrierTextController {
|
||||
}
|
||||
}
|
||||
|
||||
displayText = updateCarrierTextWithSimIoError(displayText, allSimsMissing);
|
||||
displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
|
||||
allSimsMissing);
|
||||
// APM (airplane mode) != no carrier state. There are carrier services
|
||||
// (e.g. WFC = Wi-Fi calling) which may operate in APM.
|
||||
if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
|
||||
displayText = getAirplaneModeMessage();
|
||||
}
|
||||
|
||||
Handler handler = Dependency.get(Dependency.MAIN_HANDLER);
|
||||
if (TextUtils.isEmpty(displayText)) {
|
||||
displayText = TextUtils.join(mSeparator, carrierNames);
|
||||
}
|
||||
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
|
||||
displayText,
|
||||
displayText.toString().split(mSeparator.toString()),
|
||||
anySimReadyAndInService && !missingSimsWithSubs,
|
||||
carrierNames,
|
||||
!allSimsMissing,
|
||||
subsIds);
|
||||
postToCallback(info);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void postToCallback(CarrierTextCallbackInfo info) {
|
||||
Handler handler = Dependency.get(Dependency.MAIN_HANDLER);
|
||||
final CarrierTextCallback callback = mCarrierTextCallback;
|
||||
if (callback != null) {
|
||||
handler.post(() -> callback.updateCarrierInfo(info));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Context getContext() {
|
||||
|
||||
@@ -521,16 +521,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
Log.e(TAG, "Carrier information arrays not of same length");
|
||||
}
|
||||
} else {
|
||||
mInfos[0].visible = false;
|
||||
@@ -612,8 +603,10 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
|
||||
// Only show marquee when visible
|
||||
if (visibility == VISIBLE) {
|
||||
setEllipsize(TextUtils.TruncateAt.MARQUEE);
|
||||
setSelected(true);
|
||||
} else {
|
||||
setEllipsize(TextUtils.TruncateAt.END);
|
||||
setSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.keyguard;
|
||||
|
||||
|
||||
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
|
||||
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 org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import com.android.internal.telephony.IccCardConstants;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class CarrierTextControllerTest extends SysuiTestCase {
|
||||
|
||||
private static final CharSequence SEPARATOR = " \u2014 ";
|
||||
private static final String TEST_CARRIER = "TEST_CARRIER";
|
||||
private static final SubscriptionInfo TEST_SUBSCRIPTION = new SubscriptionInfo(0, "", 0,
|
||||
TEST_CARRIER, TEST_CARRIER, 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, "");
|
||||
@Mock
|
||||
private WifiManager mWifiManager;
|
||||
@Mock
|
||||
private CarrierTextController.CarrierTextCallback mCarrierTextCallback;
|
||||
@Mock
|
||||
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock
|
||||
private ConnectivityManager mConnectivityManager;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private CarrierTextController.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
|
||||
|
||||
private CarrierTextController mCarrierTextController;
|
||||
private TestableLooper mTestableLooper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
|
||||
mContext.addMockSystemService(WifiManager.class, mWifiManager);
|
||||
mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
|
||||
mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
|
||||
mDependency.injectMockDependency(WakefulnessLifecycle.class);
|
||||
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
|
||||
new Handler(mTestableLooper.getLooper()));
|
||||
|
||||
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
|
||||
new CharSequence[]{}, false, new int[]{});
|
||||
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
|
||||
mCarrierTextController = new TestCarrierTextController(mContext, SEPARATOR, true, true,
|
||||
mKeyguardUpdateMonitor);
|
||||
// This should not start listening on any of the real dependencies
|
||||
mCarrierTextController.setListening(mCarrierTextCallback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongSlots() {
|
||||
reset(mCarrierTextCallback);
|
||||
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
|
||||
new ArrayList<>());
|
||||
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
|
||||
IccCardConstants.State.CARD_IO_ERROR);
|
||||
// This should not produce an out of bounds error, even though there are no subscriptions
|
||||
mCarrierTextController.mCallback.onSimStateChanged(0, -3,
|
||||
IccCardConstants.State.CARD_IO_ERROR);
|
||||
mCarrierTextController.mCallback.onSimStateChanged(0, 3, IccCardConstants.State.READY);
|
||||
verify(mCarrierTextCallback, never()).updateCarrierInfo(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoreSlotsThanSubs() {
|
||||
reset(mCarrierTextCallback);
|
||||
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
|
||||
new ArrayList<>());
|
||||
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
|
||||
IccCardConstants.State.CARD_IO_ERROR);
|
||||
// This should not produce an out of bounds error, even though there are no subscriptions
|
||||
mCarrierTextController.mCallback.onSimStateChanged(0, 1,
|
||||
IccCardConstants.State.CARD_IO_ERROR);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(
|
||||
any(CarrierTextController.CarrierTextCallbackInfo.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallback() {
|
||||
reset(mCarrierTextCallback);
|
||||
mCarrierTextController.postToCallback(mCarrierTextCallbackInfo);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
|
||||
ArgumentCaptor.forClass(
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
assertEquals(mCarrierTextCallbackInfo, captor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullingCallback() {
|
||||
reset(mCarrierTextCallback);
|
||||
|
||||
mCarrierTextController.postToCallback(mCarrierTextCallbackInfo);
|
||||
mCarrierTextController.setListening(null);
|
||||
|
||||
// This shouldn't produce NPE
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInfo_OneValidSubscription() {
|
||||
reset(mCarrierTextCallback);
|
||||
List<SubscriptionInfo> list = new ArrayList<>();
|
||||
list.add(TEST_SUBSCRIPTION);
|
||||
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());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
assertEquals(1, info.listOfCarriers.length);
|
||||
assertEquals(TEST_CARRIER, info.listOfCarriers[0]);
|
||||
assertEquals(1, info.subscriptionIds.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInfo_OneValidSubscriptionWithRoaming() {
|
||||
reset(mCarrierTextCallback);
|
||||
List<SubscriptionInfo> list = new ArrayList<>();
|
||||
list.add(TEST_SUBSCRIPTION_ROAMING);
|
||||
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());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
assertEquals(1, info.listOfCarriers.length);
|
||||
assertTrue(info.listOfCarriers[0].toString().contains(TEST_CARRIER));
|
||||
assertEquals(1, info.subscriptionIds.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInfo_noSubscriptions() {
|
||||
reset(mCarrierTextCallback);
|
||||
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
|
||||
new ArrayList<>());
|
||||
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
|
||||
ArgumentCaptor.forClass(
|
||||
CarrierTextController.CarrierTextCallbackInfo.class);
|
||||
|
||||
mCarrierTextController.updateCarrierText();
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
|
||||
|
||||
CarrierTextController.CarrierTextCallbackInfo info = captor.getValue();
|
||||
assertEquals(0, info.listOfCarriers.length);
|
||||
assertEquals(0, info.subscriptionIds.length);
|
||||
|
||||
}
|
||||
|
||||
public static class TestCarrierTextController extends CarrierTextController {
|
||||
private KeyguardUpdateMonitor mKUM;
|
||||
|
||||
public TestCarrierTextController(Context context, CharSequence separator,
|
||||
boolean showAirplaneMode, boolean showMissingSim, KeyguardUpdateMonitor kum) {
|
||||
super(context, separator, showAirplaneMode, showMissingSim);
|
||||
mKUM = kum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListening(CarrierTextCallback callback) {
|
||||
super.setListening(callback);
|
||||
mKeyguardUpdateMonitor = mKUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user