Loading src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +21 −3 Original line number Diff line number Diff line Loading @@ -425,11 +425,15 @@ public class SubscriptionInfoUpdater extends Handler { private void handleSimNotReady(int phoneId) { logd("handleSimNotReady: phoneId: " + phoneId); boolean isFinalState = false; IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); if (iccCard.isEmptyProfile()) { // ICC_NOT_READY is a terminal state for an eSIM on the boot profile. At this // phase, the subscription list is accessible. Treating NOT_READY if (iccCard.isEmptyProfile() || areUiccAppsDisabledOnCard(phoneId)) { isFinalState = true; // ICC_NOT_READY is a terminal state for // 1) It's an empty profile as there's no uicc applications. Or // 2) Its uicc applications are set to be disabled. // At this phase, the subscription list is accessible. Treating NOT_READY // as equivalent to ABSENT, once the rest of the system can handle it. sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */); Loading @@ -439,6 +443,20 @@ public class SubscriptionInfoUpdater extends Handler { null); broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); if (isFinalState) { updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY); } } private boolean areUiccAppsDisabledOnCard(int phoneId) { // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another // handleSimNotReady so this will be evaluated again. UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); if (slot == null || slot.getIccId() == null) return false; SubscriptionInfo info = SubscriptionController.getInstance() .getSubInfoForIccId(slot.getIccId()); return info != null && !info.areUiccApplicationsEnabled(); } private void handleSimLoaded(int phoneId) { Loading src/java/com/android/internal/telephony/uicc/UiccProfile.java +6 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,12 @@ public class UiccProfile extends IccCard { } setExternalState(IccCardConstants.State.NOT_READY); break; case APPSTATE_DETECTED: if (VDBG) { log("updateExternalState: app state is detected; setting state to NOT_READY"); } setExternalState(IccCardConstants.State.NOT_READY); break; case APPSTATE_READY: checkAndUpdateIfAnyAppToBeIgnored(); if (areAllApplicationsReady()) { Loading tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,46 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); } @Test @SmallTest public void testSimNotReady() throws Exception { mUpdater.updateInternalIccState( IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false); processAllMessages(); assertFalse(mUpdater.isSubInfoInitialized()); verify(mSubscriptionContent, never()).put(anyString(), any()); CarrierConfigManager mConfigManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); verify(mConfigManager, never()).updateConfigForPhoneId(eq(FAKE_SUB_ID_1), eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY)); verify(mSubscriptionController, never()).clearSubInfo(); verify(mSubscriptionController, never()).notifySubscriptionInfoChanged(); } @Test @SmallTest public void testSimNotReadyEmptyProfile() throws Exception { doReturn(mIccCard).when(mPhone).getIccCard(); doReturn(true).when(mIccCard).isEmptyProfile(); mUpdater.updateInternalIccState( IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false); processAllMessages(); assertTrue(mUpdater.isSubInfoInitialized()); // Sub info should be cleared and change should be notified. verify(mSubscriptionController).clearSubInfoRecord(eq(FAKE_SUB_ID_1)); verify(mSubscriptionController).notifySubscriptionInfoChanged(); // No new sub should be added. verify(mSubscriptionManager, never()).addSubscriptionInfoRecord(any(), anyInt()); verify(mSubscriptionContent, never()).put(anyString(), any()); CarrierConfigManager mConfigManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); verify(mConfigManager).updateConfigForPhoneId(eq(FAKE_SUB_ID_1), eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY)); } @Test @SmallTest public void testSimError() throws Exception { Loading tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java +13 −10 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.telephony.Annotation; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; import android.telephony.PreciseDataConnectionState; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; Loading @@ -57,7 +58,7 @@ import java.util.concurrent.atomic.AtomicInteger; @TestableLooper.RunWithLooper public class TelephonyRegistryTest extends TelephonyTest { @Mock private ISub.Stub mISubStub; private SubscriptionInfo mMockSubInfo; private PhoneStateListenerWrapper mPhoneStateListener; private TelephonyRegistry mTelephonyRegistry; private PhoneCapability mPhoneCapability; Loading Loading @@ -105,9 +106,6 @@ public class TelephonyRegistryTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp("TelephonyRegistryTest"); // ServiceManager.getService("isub") will return this stub for any call to // SubscriptionManager. mServiceManagerMockedServices.put("isub", mISubStub); mTelephonyRegistry = new TelephonyRegistry(mContext); addTelephonyRegistryService(); mPhoneStateListener = new PhoneStateListenerWrapper(); Loading @@ -124,6 +122,8 @@ public class TelephonyRegistryTest extends TelephonyTest { @Test @SmallTest public void testPhoneCapabilityChanged() { doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); // mTelephonyRegistry.listen with notifyNow = true should trigger callback immediately. PhoneCapability phoneCapability = new PhoneCapability(1, 2, 3, null, false); mTelephonyRegistry.notifyPhoneCapabilityChanged(phoneCapability); Loading Loading @@ -169,12 +169,13 @@ public class TelephonyRegistryTest extends TelephonyTest { @Test @SmallTest public void testSrvccStateChanged() throws Exception { // Return a phone ID of 0 for all sub ids given. doReturn(0/*phoneId*/).when(mISubStub).getPhoneId(anyInt()); // Return a slotIndex / phoneId of 0 for all sub ids given. doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); int srvccState = TelephonyManager.SRVCC_STATE_HANDOVER_STARTED; mTelephonyRegistry.notifySrvccStateChanged(0 /*subId*/, srvccState); mTelephonyRegistry.notifySrvccStateChanged(1 /*subId*/, srvccState); // Should receive callback when listen is called that contains the latest notify result. mTelephonyRegistry.listenForSubscriber(0 /*subId*/, mContext.getOpPackageName(), mTelephonyRegistry.listenForSubscriber(1 /*subId*/, mContext.getOpPackageName(), mPhoneStateListener.callback, LISTEN_SRVCC_STATE_CHANGED, true); processAllMessages(); Loading @@ -182,7 +183,7 @@ public class TelephonyRegistryTest extends TelephonyTest { // trigger callback srvccState = TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED; mTelephonyRegistry.notifySrvccStateChanged(0 /*subId*/, srvccState); mTelephonyRegistry.notifySrvccStateChanged(1 /*subId*/, srvccState); processAllMessages(); assertEquals(srvccState, mSrvccState); } Loading Loading @@ -244,7 +245,9 @@ public class TelephonyRegistryTest extends TelephonyTest { */ @Test public void testPreciseDataConnectionStateChanged() { final int subId = 0; final int subId = 1; doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); // Initialize the PSL with a PreciseDataConnection mTelephonyRegistry.notifyDataConnectionForSubscriber( /*phoneId*/ 0, subId, "default", Loading tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,8 @@ public abstract class TelephonyTest { protected UiccCard mUiccCard; @Mock protected MultiSimSettingController mMultiSimSettingController; @Mock protected IccCard mIccCard; protected ImsCallProfile mImsCallProfile; protected TelephonyManager mTelephonyManager; Loading Loading
src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +21 −3 Original line number Diff line number Diff line Loading @@ -425,11 +425,15 @@ public class SubscriptionInfoUpdater extends Handler { private void handleSimNotReady(int phoneId) { logd("handleSimNotReady: phoneId: " + phoneId); boolean isFinalState = false; IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); if (iccCard.isEmptyProfile()) { // ICC_NOT_READY is a terminal state for an eSIM on the boot profile. At this // phase, the subscription list is accessible. Treating NOT_READY if (iccCard.isEmptyProfile() || areUiccAppsDisabledOnCard(phoneId)) { isFinalState = true; // ICC_NOT_READY is a terminal state for // 1) It's an empty profile as there's no uicc applications. Or // 2) Its uicc applications are set to be disabled. // At this phase, the subscription list is accessible. Treating NOT_READY // as equivalent to ABSENT, once the rest of the system can handle it. sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */); Loading @@ -439,6 +443,20 @@ public class SubscriptionInfoUpdater extends Handler { null); broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); if (isFinalState) { updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY); } } private boolean areUiccAppsDisabledOnCard(int phoneId) { // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another // handleSimNotReady so this will be evaluated again. UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); if (slot == null || slot.getIccId() == null) return false; SubscriptionInfo info = SubscriptionController.getInstance() .getSubInfoForIccId(slot.getIccId()); return info != null && !info.areUiccApplicationsEnabled(); } private void handleSimLoaded(int phoneId) { Loading
src/java/com/android/internal/telephony/uicc/UiccProfile.java +6 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,12 @@ public class UiccProfile extends IccCard { } setExternalState(IccCardConstants.State.NOT_READY); break; case APPSTATE_DETECTED: if (VDBG) { log("updateExternalState: app state is detected; setting state to NOT_READY"); } setExternalState(IccCardConstants.State.NOT_READY); break; case APPSTATE_READY: checkAndUpdateIfAnyAppToBeIgnored(); if (areAllApplicationsReady()) { Loading
tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,46 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); } @Test @SmallTest public void testSimNotReady() throws Exception { mUpdater.updateInternalIccState( IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false); processAllMessages(); assertFalse(mUpdater.isSubInfoInitialized()); verify(mSubscriptionContent, never()).put(anyString(), any()); CarrierConfigManager mConfigManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); verify(mConfigManager, never()).updateConfigForPhoneId(eq(FAKE_SUB_ID_1), eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY)); verify(mSubscriptionController, never()).clearSubInfo(); verify(mSubscriptionController, never()).notifySubscriptionInfoChanged(); } @Test @SmallTest public void testSimNotReadyEmptyProfile() throws Exception { doReturn(mIccCard).when(mPhone).getIccCard(); doReturn(true).when(mIccCard).isEmptyProfile(); mUpdater.updateInternalIccState( IccCardConstants.INTENT_VALUE_ICC_NOT_READY, null, FAKE_SUB_ID_1, false); processAllMessages(); assertTrue(mUpdater.isSubInfoInitialized()); // Sub info should be cleared and change should be notified. verify(mSubscriptionController).clearSubInfoRecord(eq(FAKE_SUB_ID_1)); verify(mSubscriptionController).notifySubscriptionInfoChanged(); // No new sub should be added. verify(mSubscriptionManager, never()).addSubscriptionInfoRecord(any(), anyInt()); verify(mSubscriptionContent, never()).put(anyString(), any()); CarrierConfigManager mConfigManager = (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); verify(mConfigManager).updateConfigForPhoneId(eq(FAKE_SUB_ID_1), eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY)); } @Test @SmallTest public void testSimError() throws Exception { Loading
tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java +13 −10 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.telephony.Annotation; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; import android.telephony.PreciseDataConnectionState; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; Loading @@ -57,7 +58,7 @@ import java.util.concurrent.atomic.AtomicInteger; @TestableLooper.RunWithLooper public class TelephonyRegistryTest extends TelephonyTest { @Mock private ISub.Stub mISubStub; private SubscriptionInfo mMockSubInfo; private PhoneStateListenerWrapper mPhoneStateListener; private TelephonyRegistry mTelephonyRegistry; private PhoneCapability mPhoneCapability; Loading Loading @@ -105,9 +106,6 @@ public class TelephonyRegistryTest extends TelephonyTest { @Before public void setUp() throws Exception { super.setUp("TelephonyRegistryTest"); // ServiceManager.getService("isub") will return this stub for any call to // SubscriptionManager. mServiceManagerMockedServices.put("isub", mISubStub); mTelephonyRegistry = new TelephonyRegistry(mContext); addTelephonyRegistryService(); mPhoneStateListener = new PhoneStateListenerWrapper(); Loading @@ -124,6 +122,8 @@ public class TelephonyRegistryTest extends TelephonyTest { @Test @SmallTest public void testPhoneCapabilityChanged() { doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); // mTelephonyRegistry.listen with notifyNow = true should trigger callback immediately. PhoneCapability phoneCapability = new PhoneCapability(1, 2, 3, null, false); mTelephonyRegistry.notifyPhoneCapabilityChanged(phoneCapability); Loading Loading @@ -169,12 +169,13 @@ public class TelephonyRegistryTest extends TelephonyTest { @Test @SmallTest public void testSrvccStateChanged() throws Exception { // Return a phone ID of 0 for all sub ids given. doReturn(0/*phoneId*/).when(mISubStub).getPhoneId(anyInt()); // Return a slotIndex / phoneId of 0 for all sub ids given. doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); int srvccState = TelephonyManager.SRVCC_STATE_HANDOVER_STARTED; mTelephonyRegistry.notifySrvccStateChanged(0 /*subId*/, srvccState); mTelephonyRegistry.notifySrvccStateChanged(1 /*subId*/, srvccState); // Should receive callback when listen is called that contains the latest notify result. mTelephonyRegistry.listenForSubscriber(0 /*subId*/, mContext.getOpPackageName(), mTelephonyRegistry.listenForSubscriber(1 /*subId*/, mContext.getOpPackageName(), mPhoneStateListener.callback, LISTEN_SRVCC_STATE_CHANGED, true); processAllMessages(); Loading @@ -182,7 +183,7 @@ public class TelephonyRegistryTest extends TelephonyTest { // trigger callback srvccState = TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED; mTelephonyRegistry.notifySrvccStateChanged(0 /*subId*/, srvccState); mTelephonyRegistry.notifySrvccStateChanged(1 /*subId*/, srvccState); processAllMessages(); assertEquals(srvccState, mSrvccState); } Loading Loading @@ -244,7 +245,9 @@ public class TelephonyRegistryTest extends TelephonyTest { */ @Test public void testPreciseDataConnectionStateChanged() { final int subId = 0; final int subId = 1; doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex(); // Initialize the PSL with a PreciseDataConnection mTelephonyRegistry.notifyDataConnectionForSubscriber( /*phoneId*/ 0, subId, "default", Loading
tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -268,6 +268,8 @@ public abstract class TelephonyTest { protected UiccCard mUiccCard; @Mock protected MultiSimSettingController mMultiSimSettingController; @Mock protected IccCard mIccCard; protected ImsCallProfile mImsCallProfile; protected TelephonyManager mTelephonyManager; Loading