Loading src/java/com/android/internal/telephony/uicc/UiccController.java +70 −19 Original line number Diff line number Diff line Loading @@ -155,6 +155,9 @@ public class UiccController extends Handler { // SharedPreference key for saving the known card strings (ICCIDs and EIDs) ordered by card ID private static final String CARD_STRINGS = "card_strings"; // Whether the device has an eUICC built in. private boolean mHasBuiltInEuicc = false; // SharedPreferences key for saving the default euicc card ID private static final String DEFAULT_CARD = "default_card"; Loading @@ -162,7 +165,8 @@ public class UiccController extends Handler { private static final Object mLock = new Object(); @UnsupportedAppUsage private static UiccController mInstance; private static ArrayList<IccSlotStatus> sLastSlotStatus; @VisibleForTesting public static ArrayList<IccSlotStatus> sLastSlotStatus; @UnsupportedAppUsage @VisibleForTesting Loading Loading @@ -230,6 +234,8 @@ public class UiccController extends Handler { mLauncher = new UiccStateChangedLauncher(c, this); mCardStrings = loadCardStrings(); mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; mHasBuiltInEuicc = hasBuiltInEuicc(); } /** Loading Loading @@ -789,7 +795,6 @@ public class UiccController extends Handler { int numActiveSlots = 0; boolean isDefaultEuiccCardIdSet = false; boolean anyEuiccIsActive = false; boolean hasEuicc = false; for (int i = 0; i < status.size(); i++) { IccSlotStatus iss = status.get(i); boolean isActive = (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE); Loading Loading @@ -821,7 +826,6 @@ public class UiccController extends Handler { } if (mUiccSlots[i].isEuicc()) { hasEuicc = true; if (isActive) { anyEuiccIsActive = true; } Loading @@ -833,11 +837,10 @@ public class UiccController extends Handler { addCardId(eid); // whenever slot status is received, set default card to the eUICC with the // lowest slot index. if (!isDefaultEuiccCardIdSet) { // whenever slot status is received, set default card to the non-removable eUICC // with the lowest slot index. if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { isDefaultEuiccCardIdSet = true; // TODO(b/122738148) the default eUICC should not be removable mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "Using eid=" + eid + " in slot=" + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId; Loading @@ -847,11 +850,37 @@ public class UiccController extends Handler { } } if (hasEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { log("onGetSlotStatusDone: setting TEMPORARILY_UNSUPPORTED_CARD_ID"); isDefaultEuiccCardIdSet = true; mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; } if (!mHasBuiltInEuicc && !isDefaultEuiccCardIdSet) { // if there are no built-in eUICCs, then consider setting a removable eUICC to the // default. // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not // correspond to any slot in mUiccSlots. This logic is still safe in that case because // SlotStatus is only for HAL >= 1.2 for (int i = 0; i < status.size(); i++) { if (mUiccSlots[i].isEuicc()) { isDefaultEuiccCardIdSet = true; String eid = status.get(i).eid; if (!TextUtils.isEmpty(eid)) { mDefaultEuiccCardId = convertToPublicCardId(eid); log("Using eid=" + eid + " from removable eUICC in slot=" + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); break; } } } } if (!isDefaultEuiccCardIdSet) { // no eUICCs at all mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; } if (VDBG) logPhoneIdToSlotIdMapping(); // sanity check: number of active slots should be valid Loading Loading @@ -954,8 +983,9 @@ public class UiccController extends Handler { mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); } // for RadioConfig 1.2 or higher, the EID comes with the IccSlotStatus // for RadioConfig<1.2 we register for EID ready set mCardStrings and mDefaultEuiccCardId here // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID // is first loaded private void onEidReady(AsyncResult ar, Integer index) { if (ar.exception != null) { Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); Loading @@ -967,25 +997,45 @@ public class UiccController extends Handler { return; } int slotId = mPhoneIdToSlotId[index]; UiccCard card = mUiccSlots[slotId].getUiccCard(); EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); if (card == null) { Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); return; } // set mCardStrings and the defaultEuiccCardId using the now available EID String eid = ((EuiccCard) card).getEid(); String eid = card.getEid(); addCardId(eid); if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { // TODO(b/122738148) the default eUICC should not be removable if (!mUiccSlots[slotId].isRemovable()) { mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "onEidReady: eid=" + eid + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; String logStr = "onEidReady: eid=" + eid + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; sLocalLog.log(logStr); log(logStr); } else if (!mHasBuiltInEuicc) { // we only set a removable eUICC to the default if there are no non-removable eUICCs mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "onEidReady: eid=" + eid + " from removable eUICC in slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; sLocalLog.log(logStr); log(logStr); } } ((EuiccCard) card).unregisterForEidReady(this); card.unregisterForEidReady(this); } // Return true if the device has at least one built in eUICC based on the resource overlay private boolean hasBuiltInEuicc() { int[] euiccSlots = mContext.getResources() .getIntArray(com.android.internal.R.array.non_removable_euicc_slots); if (euiccSlots == null || euiccSlots.length == 0) { log("hasBuiltInEuicc: non_removable_euicc_slots resource is empty; returning false."); return false; } log("hasBuiltInEuicc: non_removable_euicc_slots resource not empty, returning true"); return true; } /** Loading Loading @@ -1029,6 +1079,7 @@ public class UiccController extends Handler { pw.println(); pw.flush(); pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext)); pw.println(" mHasBuiltInEuicc=" + mHasBuiltInEuicc); pw.println(" mUiccSlots: size=" + mUiccSlots.length); pw.println(" mCardStrings=" + mCardStrings); pw.println(" mDefaultEuiccCardId=" + mDefaultEuiccCardId); Loading src/java/com/android/internal/telephony/uicc/UiccSlot.java +1 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,7 @@ public class UiccSlot extends Handler { pw.println(" mCi=" + mCi); pw.println(" mActive=" + mActive); pw.println(" mIsEuicc=" + mIsEuicc); pw.println(" mIsRemovable=" + mIsRemovable); pw.println(" mLastRadioState=" + mLastRadioState); pw.println(" mIccId=" + mIccId); pw.println(" mCardState=" + mCardState); Loading tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java +157 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,12 @@ package com.android.internal.telephony.uicc; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doReturn; Loading @@ -30,6 +33,7 @@ import android.os.AsyncResult; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.preference.PreferenceManager; import android.telephony.TelephonyManager; import android.telephony.UiccCardInfo; Loading Loading @@ -62,6 +66,8 @@ public class UiccControllerTest extends TelephonyTest { @Mock private UiccSlot mMockSlot; @Mock private UiccSlot mMockRemovableEuiccSlot; @Mock private UiccCard mMockCard; @Mock private EuiccCard mMockEuiccCard; Loading Loading @@ -95,6 +101,9 @@ public class UiccControllerTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp(this.getClass().getSimpleName()); // some tests use use the shared preferences in the runner context, so reset them here PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getContext()) .edit().clear().commit(); doReturn(PHONE_COUNT).when(mTelephonyManager).getPhoneCount(); doReturn(PHONE_COUNT).when(mTelephonyManager).getSimCount(); Loading @@ -115,6 +124,8 @@ public class UiccControllerTest extends TelephonyTest { mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG); mUiccControllerHandlerThread.start(); waitUntilReady(); // reset sLastSlotStatus so that onGetSlotStatusDone always sees a change in the slot status mUiccControllerUT.sLastSlotStatus = null; /* expected to get new UiccCards being created wait till the async result and message delay */ waitForMs(100); Loading @@ -126,6 +137,23 @@ public class UiccControllerTest extends TelephonyTest { super.tearDown(); } /** * Replace num slots and euicc slots resources and reinstantiate the UiccController */ private void reconfigureSlots(int numSlots, int[] nonRemovableEuiccSlots) throws Exception { mContextFixture.putIntResource(com.android.internal.R.integer.config_num_physical_slots, numSlots); mContextFixture.putIntArrayResource( com.android.internal.R.array.non_removable_euicc_slots, nonRemovableEuiccSlots); replaceInstance(UiccController.class, "mInstance", null, null); mUiccControllerHandlerThread.quit(); mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG); mUiccControllerHandlerThread.start(); waitUntilReady(); waitForMs(100); } @Test @SmallTest public void testSanity() { // radio power is expected to be on which should trigger icc card and slot status requests Loading Loading @@ -395,4 +423,133 @@ public class UiccControllerTest extends TelephonyTest { assertEquals(TelephonyManager.UNSUPPORTED_CARD_ID, mUiccControllerUT.getCardIdForDefaultEuicc()); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC. */ @Test public void testDefaultEuiccIsNotRemovable() { try { reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */); } catch (Exception e) { fail("Unable to reconfigure slots."); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots so that [0] is a removable eUICC and [1] is built-in mUiccControllerUT.mUiccSlots[0] = mMockRemovableEuiccSlot; doReturn(true).when(mMockRemovableEuiccSlot).isEuicc(); doReturn(true).when(mMockRemovableEuiccSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(1 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC is the non-removable eUICC assertEquals(mUiccControllerUT.convertToPublicCardId(iss2.eid), mUiccControllerUT.getCardIdForDefaultEuicc()); assertTrue(mUiccControllerUT.convertToPublicCardId(iss2.eid) >= 0); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC. This should * not depend on the order of the slots. */ @Test public void testDefaultEuiccIsNotRemovable_swapSlotOrder() { try { reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */); } catch (Exception e) { fail("Unable to reconfigure slots."); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots so that [0] is a built-in eUICC and [1] is removable mUiccControllerUT.mUiccSlots[0] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot; doReturn(true).when(mMockRemovableEuiccSlot).isEuicc(); doReturn(true).when(mMockRemovableEuiccSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(1 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC is the non-removable eUICC assertEquals(mUiccControllerUT.convertToPublicCardId(iss1.eid), mUiccControllerUT.getCardIdForDefaultEuicc()); assertTrue(mUiccControllerUT.convertToPublicCardId(iss1.eid) >= 0); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC, even if that * eUICC is inactive. * When there is a built-in eUICC which is inactive, we set the mDefaultEuiccCardId to * TEMPORARILY_UNSUPPORTED_CARD_ID. */ @Test public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() { try { reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */); } catch (Exception e) { fail(); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots. Slot 0 is inactive here. mUiccControllerUT.mUiccSlots[0] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(true).when(mMockSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(0 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC cardId is TEMPORARILY_UNSUPPORTED_CARD_ID assertEquals(TelephonyManager.UNSUPPORTED_CARD_ID, mUiccControllerUT.getCardIdForDefaultEuicc()); } } Loading
src/java/com/android/internal/telephony/uicc/UiccController.java +70 −19 Original line number Diff line number Diff line Loading @@ -155,6 +155,9 @@ public class UiccController extends Handler { // SharedPreference key for saving the known card strings (ICCIDs and EIDs) ordered by card ID private static final String CARD_STRINGS = "card_strings"; // Whether the device has an eUICC built in. private boolean mHasBuiltInEuicc = false; // SharedPreferences key for saving the default euicc card ID private static final String DEFAULT_CARD = "default_card"; Loading @@ -162,7 +165,8 @@ public class UiccController extends Handler { private static final Object mLock = new Object(); @UnsupportedAppUsage private static UiccController mInstance; private static ArrayList<IccSlotStatus> sLastSlotStatus; @VisibleForTesting public static ArrayList<IccSlotStatus> sLastSlotStatus; @UnsupportedAppUsage @VisibleForTesting Loading Loading @@ -230,6 +234,8 @@ public class UiccController extends Handler { mLauncher = new UiccStateChangedLauncher(c, this); mCardStrings = loadCardStrings(); mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; mHasBuiltInEuicc = hasBuiltInEuicc(); } /** Loading Loading @@ -789,7 +795,6 @@ public class UiccController extends Handler { int numActiveSlots = 0; boolean isDefaultEuiccCardIdSet = false; boolean anyEuiccIsActive = false; boolean hasEuicc = false; for (int i = 0; i < status.size(); i++) { IccSlotStatus iss = status.get(i); boolean isActive = (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE); Loading Loading @@ -821,7 +826,6 @@ public class UiccController extends Handler { } if (mUiccSlots[i].isEuicc()) { hasEuicc = true; if (isActive) { anyEuiccIsActive = true; } Loading @@ -833,11 +837,10 @@ public class UiccController extends Handler { addCardId(eid); // whenever slot status is received, set default card to the eUICC with the // lowest slot index. if (!isDefaultEuiccCardIdSet) { // whenever slot status is received, set default card to the non-removable eUICC // with the lowest slot index. if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { isDefaultEuiccCardIdSet = true; // TODO(b/122738148) the default eUICC should not be removable mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "Using eid=" + eid + " in slot=" + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId; Loading @@ -847,11 +850,37 @@ public class UiccController extends Handler { } } if (hasEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { log("onGetSlotStatusDone: setting TEMPORARILY_UNSUPPORTED_CARD_ID"); isDefaultEuiccCardIdSet = true; mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; } if (!mHasBuiltInEuicc && !isDefaultEuiccCardIdSet) { // if there are no built-in eUICCs, then consider setting a removable eUICC to the // default. // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not // correspond to any slot in mUiccSlots. This logic is still safe in that case because // SlotStatus is only for HAL >= 1.2 for (int i = 0; i < status.size(); i++) { if (mUiccSlots[i].isEuicc()) { isDefaultEuiccCardIdSet = true; String eid = status.get(i).eid; if (!TextUtils.isEmpty(eid)) { mDefaultEuiccCardId = convertToPublicCardId(eid); log("Using eid=" + eid + " from removable eUICC in slot=" + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); break; } } } } if (!isDefaultEuiccCardIdSet) { // no eUICCs at all mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; } if (VDBG) logPhoneIdToSlotIdMapping(); // sanity check: number of active slots should be valid Loading Loading @@ -954,8 +983,9 @@ public class UiccController extends Handler { mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); } // for RadioConfig 1.2 or higher, the EID comes with the IccSlotStatus // for RadioConfig<1.2 we register for EID ready set mCardStrings and mDefaultEuiccCardId here // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID // is first loaded private void onEidReady(AsyncResult ar, Integer index) { if (ar.exception != null) { Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); Loading @@ -967,25 +997,45 @@ public class UiccController extends Handler { return; } int slotId = mPhoneIdToSlotId[index]; UiccCard card = mUiccSlots[slotId].getUiccCard(); EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); if (card == null) { Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); return; } // set mCardStrings and the defaultEuiccCardId using the now available EID String eid = ((EuiccCard) card).getEid(); String eid = card.getEid(); addCardId(eid); if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { // TODO(b/122738148) the default eUICC should not be removable if (!mUiccSlots[slotId].isRemovable()) { mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "onEidReady: eid=" + eid + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; String logStr = "onEidReady: eid=" + eid + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; sLocalLog.log(logStr); log(logStr); } else if (!mHasBuiltInEuicc) { // we only set a removable eUICC to the default if there are no non-removable eUICCs mDefaultEuiccCardId = convertToPublicCardId(eid); String logStr = "onEidReady: eid=" + eid + " from removable eUICC in slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId; sLocalLog.log(logStr); log(logStr); } } ((EuiccCard) card).unregisterForEidReady(this); card.unregisterForEidReady(this); } // Return true if the device has at least one built in eUICC based on the resource overlay private boolean hasBuiltInEuicc() { int[] euiccSlots = mContext.getResources() .getIntArray(com.android.internal.R.array.non_removable_euicc_slots); if (euiccSlots == null || euiccSlots.length == 0) { log("hasBuiltInEuicc: non_removable_euicc_slots resource is empty; returning false."); return false; } log("hasBuiltInEuicc: non_removable_euicc_slots resource not empty, returning true"); return true; } /** Loading Loading @@ -1029,6 +1079,7 @@ public class UiccController extends Handler { pw.println(); pw.flush(); pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext)); pw.println(" mHasBuiltInEuicc=" + mHasBuiltInEuicc); pw.println(" mUiccSlots: size=" + mUiccSlots.length); pw.println(" mCardStrings=" + mCardStrings); pw.println(" mDefaultEuiccCardId=" + mDefaultEuiccCardId); Loading
src/java/com/android/internal/telephony/uicc/UiccSlot.java +1 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,7 @@ public class UiccSlot extends Handler { pw.println(" mCi=" + mCi); pw.println(" mActive=" + mActive); pw.println(" mIsEuicc=" + mIsEuicc); pw.println(" mIsRemovable=" + mIsRemovable); pw.println(" mLastRadioState=" + mLastRadioState); pw.println(" mIccId=" + mIccId); pw.println(" mCardState=" + mCardState); Loading
tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java +157 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,12 @@ package com.android.internal.telephony.uicc; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doReturn; Loading @@ -30,6 +33,7 @@ import android.os.AsyncResult; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.preference.PreferenceManager; import android.telephony.TelephonyManager; import android.telephony.UiccCardInfo; Loading Loading @@ -62,6 +66,8 @@ public class UiccControllerTest extends TelephonyTest { @Mock private UiccSlot mMockSlot; @Mock private UiccSlot mMockRemovableEuiccSlot; @Mock private UiccCard mMockCard; @Mock private EuiccCard mMockEuiccCard; Loading Loading @@ -95,6 +101,9 @@ public class UiccControllerTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp(this.getClass().getSimpleName()); // some tests use use the shared preferences in the runner context, so reset them here PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getContext()) .edit().clear().commit(); doReturn(PHONE_COUNT).when(mTelephonyManager).getPhoneCount(); doReturn(PHONE_COUNT).when(mTelephonyManager).getSimCount(); Loading @@ -115,6 +124,8 @@ public class UiccControllerTest extends TelephonyTest { mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG); mUiccControllerHandlerThread.start(); waitUntilReady(); // reset sLastSlotStatus so that onGetSlotStatusDone always sees a change in the slot status mUiccControllerUT.sLastSlotStatus = null; /* expected to get new UiccCards being created wait till the async result and message delay */ waitForMs(100); Loading @@ -126,6 +137,23 @@ public class UiccControllerTest extends TelephonyTest { super.tearDown(); } /** * Replace num slots and euicc slots resources and reinstantiate the UiccController */ private void reconfigureSlots(int numSlots, int[] nonRemovableEuiccSlots) throws Exception { mContextFixture.putIntResource(com.android.internal.R.integer.config_num_physical_slots, numSlots); mContextFixture.putIntArrayResource( com.android.internal.R.array.non_removable_euicc_slots, nonRemovableEuiccSlots); replaceInstance(UiccController.class, "mInstance", null, null); mUiccControllerHandlerThread.quit(); mUiccControllerHandlerThread = new UiccControllerHandlerThread(TAG); mUiccControllerHandlerThread.start(); waitUntilReady(); waitForMs(100); } @Test @SmallTest public void testSanity() { // radio power is expected to be on which should trigger icc card and slot status requests Loading Loading @@ -395,4 +423,133 @@ public class UiccControllerTest extends TelephonyTest { assertEquals(TelephonyManager.UNSUPPORTED_CARD_ID, mUiccControllerUT.getCardIdForDefaultEuicc()); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC. */ @Test public void testDefaultEuiccIsNotRemovable() { try { reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */); } catch (Exception e) { fail("Unable to reconfigure slots."); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots so that [0] is a removable eUICC and [1] is built-in mUiccControllerUT.mUiccSlots[0] = mMockRemovableEuiccSlot; doReturn(true).when(mMockRemovableEuiccSlot).isEuicc(); doReturn(true).when(mMockRemovableEuiccSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(1 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC is the non-removable eUICC assertEquals(mUiccControllerUT.convertToPublicCardId(iss2.eid), mUiccControllerUT.getCardIdForDefaultEuicc()); assertTrue(mUiccControllerUT.convertToPublicCardId(iss2.eid) >= 0); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC. This should * not depend on the order of the slots. */ @Test public void testDefaultEuiccIsNotRemovable_swapSlotOrder() { try { reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */); } catch (Exception e) { fail("Unable to reconfigure slots."); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots so that [0] is a built-in eUICC and [1] is removable mUiccControllerUT.mUiccSlots[0] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot; doReturn(true).when(mMockRemovableEuiccSlot).isEuicc(); doReturn(true).when(mMockRemovableEuiccSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(1 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC is the non-removable eUICC assertEquals(mUiccControllerUT.convertToPublicCardId(iss1.eid), mUiccControllerUT.getCardIdForDefaultEuicc()); assertTrue(mUiccControllerUT.convertToPublicCardId(iss1.eid) >= 0); } /** * The default eUICC should not be the removable slot if there is a built-in eUICC, even if that * eUICC is inactive. * When there is a built-in eUICC which is inactive, we set the mDefaultEuiccCardId to * TEMPORARILY_UNSUPPORTED_CARD_ID. */ @Test public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() { try { reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */); } catch (Exception e) { fail(); } // Give UiccController a real context so it can use shared preferences mUiccControllerUT.mContext = InstrumentationRegistry.getContext(); // Mock out UiccSlots. Slot 0 is inactive here. mUiccControllerUT.mUiccSlots[0] = mMockSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(false).when(mMockSlot).isRemovable(); mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot; doReturn(true).when(mMockSlot).isEuicc(); doReturn(true).when(mMockSlot).isRemovable(); // simulate slot status loaded so that the UiccController sets the card ID IccSlotStatus iss1 = new IccSlotStatus(); iss1.setSlotState(0 /* active */); iss1.eid = "AB123456"; IccSlotStatus iss2 = new IccSlotStatus(); iss2.setSlotState(1 /* active */); iss2.eid = "ZYW13094"; ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>(); status.add(iss1); status.add(iss2); AsyncResult ar = new AsyncResult(null, status, null); Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar); mUiccControllerUT.handleMessage(msg); // assert that the default eUICC cardId is TEMPORARILY_UNSUPPORTED_CARD_ID assertEquals(TelephonyManager.UNSUPPORTED_CARD_ID, mUiccControllerUT.getCardIdForDefaultEuicc()); } }