Add a subscription record in simTable for inactive SIM.
We need a subId if we want to enable a SIM in an inactive
SIM slot.
Bug: 149359276
Test: unittest and manual - add a new pSIM in single SIM
device with eSIM active. Verify that pSIM record is added
and it shows up in Settings page.
Change-Id: Ifb9e5594d1abcd0b8270cfe9ec0c5260e8d86eb1
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index 44bfcc9..4a17582 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -1493,9 +1493,10 @@
value.put(SubscriptionManager.CARRIER_NAME, "");
value.put(SubscriptionManager.CARD_ID, uniqueId);
value.put(SubscriptionManager.SUBSCRIPTION_TYPE, subscriptionType);
- if (isSubscriptionForRemoteSim(subscriptionType)) {
+ if (!TextUtils.isEmpty(displayName)) {
value.put(SubscriptionManager.DISPLAY_NAME, displayName);
- } else {
+ }
+ if (!isSubscriptionForRemoteSim(subscriptionType)) {
UiccCard card = mUiccController.getUiccCardForPhone(slotIndex);
if (card != null) {
String cardId = card.getCardId();
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index fe600d6..a978c9a 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -91,6 +91,7 @@
private static final int EVENT_SIM_IMSI = 11;
private static final int EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS = 12;
private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 13;
+ private static final int EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED = 14;
private static final String ICCID_STRING_FOR_NO_SIM = "";
@@ -176,16 +177,26 @@
/**
* Update subscriptions when given a new ICC state.
*/
- public void updateInternalIccState(String simStatus, String reason, int phoneId,
- boolean absentAndInactive) {
+ public void updateInternalIccState(String simStatus, String reason, int phoneId) {
logd("updateInternalIccState to simStatus " + simStatus + " reason " + reason
+ " phoneId " + phoneId);
int message = internalIccStateToMessage(simStatus);
if (message != EVENT_INVALID) {
- sendMessage(obtainMessage(message, phoneId, absentAndInactive ? 1 : 0, reason));
+ sendMessage(obtainMessage(message, phoneId, 0, reason));
}
}
+ /**
+ * Update subscriptions if needed when there's a change in inactive slot.
+ * @param prevActivePhoneId is the corresponding phoneId of the slot if slot was previously
+ * active. It could be INVALID if it was already inactive.
+ * @param iccId iccId in that slot, if any.
+ */
+ public void updateInternalIccStateForInactiveSlot(int prevActivePhoneId, String iccId) {
+ sendMessage(obtainMessage(EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED, prevActivePhoneId,
+ 0, iccId));
+ }
+
private int internalIccStateToMessage(String simStatus) {
switch(simStatus) {
case IccCardConstants.INTENT_VALUE_ICC_ABSENT: return EVENT_SIM_ABSENT;
@@ -246,7 +257,11 @@
break;
case EVENT_SIM_ABSENT:
- handleSimAbsent(msg.arg1, msg.arg2);
+ handleSimAbsent(msg.arg1);
+ break;
+
+ case EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED:
+ handleInactiveSlotIccStateChange(msg.arg1, (String) msg.obj);
break;
case EVENT_SIM_LOCKED:
@@ -582,10 +597,31 @@
}
}
- private void handleSimAbsent(int phoneId, int absentAndInactive) {
- if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
- logd("SIM" + (phoneId + 1) + " hot plug out, absentAndInactive=" + absentAndInactive);
+ /**
+ * PhoneId is the corresponding phoneId of the slot if slot was previously active.
+ * It could be INVALID if it was already inactive.
+ */
+ private void handleInactiveSlotIccStateChange(int phoneId, String iccId) {
+ // If phoneId is valid, it means the physical slot was active in that phoneId. In this case,
+ // we clear (mark inactive) the subscription in db on that phone.
+ if (SubscriptionManager.isValidPhoneId(phoneId)) {
+ if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
+ logd("Slot of SIM" + (phoneId + 1) + " becomes inactive");
+ }
+ cleanSubscriptionInPhone(phoneId);
}
+ if (!TextUtils.isEmpty(iccId)) {
+ // If iccId is new, add a subscription record in the db.
+ String strippedIccId = IccUtils.stripTrailingFs(iccId);
+ if (SubscriptionController.getInstance().getSubInfoForIccId(strippedIccId) == null) {
+ SubscriptionController.getInstance().insertEmptySubInfoRecord(
+ strippedIccId, "CARD", SubscriptionManager.INVALID_PHONE_INDEX,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ }
+ }
+ }
+
+ private void cleanSubscriptionInPhone(int phoneId) {
sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
int[] subIds = SubscriptionController.getInstance().getSubId(phoneId);
if (subIds != null && subIds.length > 0) {
@@ -597,15 +633,23 @@
SubscriptionController.getSelectionForSubIdList(subIds), null);
}
updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
- // Do not broadcast if the SIM is absent and inactive, because the logical phoneId here is
- // no longer correct
- if (absentAndInactive == 0) {
- broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null);
- broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT);
- broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN);
- updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
- updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+ }
+
+ private void handleSimAbsent(int phoneId) {
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) {
+ logd("handleSimAbsent on invalid phoneId");
+ return;
}
+ if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
+ logd("SIM" + (phoneId + 1) + " hot plug out");
+ }
+ cleanSubscriptionInPhone(phoneId);
+
+ broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null);
+ broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT);
+ broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN);
+ updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+ updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
}
private void handleSimError(int phoneId) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index cd59849..0de6a53 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -36,6 +36,7 @@
import android.preference.PreferenceManager;
import android.sysprop.TelephonyProperties;
import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.text.TextUtils;
@@ -637,23 +638,33 @@
}
}
- static void updateInternalIccState(Context context, IccCardConstants.State state, String reason,
- int phoneId) {
- updateInternalIccState(context, state, reason, phoneId, false);
+ static void updateInternalIccStateForInactiveSlot(
+ Context context, int prevActivePhoneId, String iccId) {
+ if (SubscriptionManager.isValidPhoneId(prevActivePhoneId)) {
+ // Mark SIM state as ABSENT on previously phoneId.
+ TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ telephonyManager.setSimStateForPhone(prevActivePhoneId,
+ IccCardConstants.State.ABSENT.toString());
+ }
+
+ SubscriptionInfoUpdater subInfoUpdator = PhoneFactory.getSubscriptionInfoUpdater();
+ if (subInfoUpdator != null) {
+ subInfoUpdator.updateInternalIccStateForInactiveSlot(prevActivePhoneId, iccId);
+ } else {
+ Rlog.e(LOG_TAG, "subInfoUpdate is null.");
+ }
}
- // absentAndInactive is a special case when we need to update subscriptions but don't want to
- // broadcast a state change
static void updateInternalIccState(Context context, IccCardConstants.State state, String reason,
- int phoneId, boolean absentAndInactive) {
+ int phoneId) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
telephonyManager.setSimStateForPhone(phoneId, state.toString());
SubscriptionInfoUpdater subInfoUpdator = PhoneFactory.getSubscriptionInfoUpdater();
if (subInfoUpdator != null) {
- subInfoUpdator.updateInternalIccState(getIccStateIntentString(state),
- reason, phoneId, absentAndInactive);
+ subInfoUpdator.updateInternalIccState(getIccStateIntentString(state), reason, phoneId);
} else {
Rlog.e(LOG_TAG, "subInfoUpdate is null.");
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index db0aeb7..24e5a31 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -154,12 +154,10 @@
if (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_INACTIVE) {
// TODO: (b/79432584) evaluate whether should broadcast card state change
// even if it's inactive.
+ UiccController.updateInternalIccStateForInactiveSlot(mContext, mPhoneId, mIccId);
if (mActive) {
mActive = false;
mLastRadioState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
- UiccController.updateInternalIccState(
- mContext, IccCardConstants.State.ABSENT, null, mPhoneId,
- true /* special notification for absent card in an inactive slot */);
mPhoneId = INVALID_PHONE_ID;
nullifyUiccCard(true /* sim state is unknown */);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index 18740c1..db31f37 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
@@ -181,7 +181,7 @@
doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController)
.getActiveSubIdList(/*visibleOnly*/false);
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -207,8 +207,7 @@
.getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController)
.getActiveSubIdList(/*visibleOnly*/false);
- mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1, true);
+ mUpdater.updateInternalIccStateForInactiveSlot(FAKE_SUB_ID_1, null);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -228,7 +227,7 @@
@SmallTest
public void testSimUnknown() throws Exception {
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, FAKE_SUB_ID_1);
processAllMessages();
assertFalse(mUpdater.isSubInfoInitialized());
@@ -245,7 +244,7 @@
@SmallTest
public void testSimNotReady() throws Exception {
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1);
processAllMessages();
assertFalse(mUpdater.isSubInfoInitialized());
@@ -265,7 +264,7 @@
doReturn(true).when(mIccCard).isEmptyProfile();
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -285,7 +284,7 @@
@SmallTest
public void testSimError() throws Exception {
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR, null, FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -302,7 +301,7 @@
@SmallTest
public void testWrongSimState() throws Exception {
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_IMSI, null, 2, false);
+ IccCardConstants.INTENT_VALUE_ICC_IMSI, null, 2);
processAllMessages();
assertFalse(mUpdater.isSubInfoInitialized());
@@ -327,7 +326,7 @@
true);
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -393,7 +392,7 @@
doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
.getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -420,7 +419,7 @@
doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
.getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOCKED, "TESTING", FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOCKED, "TESTING", FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -470,7 +469,7 @@
doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
.getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1));
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_1);
processAllMessages();
verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(anyString(), anyInt());
@@ -485,7 +484,7 @@
doReturn("89012604200000000001").when(mIccRecord).getFullIccId();
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_2, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOADED, null, FAKE_SUB_ID_2);
processAllMessages();
verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(eq("89012604200000000000"),
@@ -507,7 +506,7 @@
new String[]{"89012604200000000000"});
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOCKED, "TESTING", FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOCKED, "TESTING", FAKE_SUB_ID_1);
processAllMessages();
assertTrue(mUpdater.isSubInfoInitialized());
@@ -657,7 +656,7 @@
// Mock sending a sim loaded for SIM 1
mUpdater.updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, "TESTING", FAKE_SUB_ID_1, false);
+ IccCardConstants.INTENT_VALUE_ICC_LOADED, "TESTING", FAKE_SUB_ID_1);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index e6e7fb8..2f2b582 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -155,7 +155,7 @@
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
assertEquals(iss.iccid, mUiccSlot.getIccId());
verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId, false);
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId);
// update slot to active
mUiccSlot.update(mSimulatedCommands, iss, 0 /* slotIndex */);
@@ -243,7 +243,7 @@
mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_ABSENT;
mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId, false);
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId);
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
assertNull(mUiccSlot.getUiccCard());
}
@@ -272,11 +272,10 @@
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
// assert that we tried to update subscriptions
- verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, activeIss.logicalSlotIndex, true);
+ verify(mSubInfoRecordUpdater).updateInternalIccStateForInactiveSlot(
+ activeIss.logicalSlotIndex, inactiveIss.iccid);
}
-
@Test
@SmallTest
public void testUiccSlotCreateAndDispose() {
@@ -296,7 +295,7 @@
mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_ABSENT;
mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId, false);
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId);
verify(mUiccProfile).dispose();
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
assertNull(mUiccSlot.getUiccCard());
@@ -321,7 +320,7 @@
// Verify that UNKNOWN state is sent to SubscriptionInfoUpdater in this case.
verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, phoneId, false);
+ IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, phoneId);
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
assertNull(mUiccSlot.getUiccCard());
@@ -331,7 +330,7 @@
// Verify that ABSENT state is sent to SubscriptionInfoUpdater in this case.
verify(mSubInfoRecordUpdater).updateInternalIccState(
- IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId, false);
+ IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, phoneId);
assertEquals(IccCardStatus.CardState.CARDSTATE_ABSENT, mUiccSlot.getCardState());
assertNull(mUiccSlot.getUiccCard());
}