Loading src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +30 −6 Original line number Diff line number Diff line Loading @@ -203,6 +203,13 @@ public class SubscriptionInfoUpdater extends Handler { sendMessage(obtainMessage(EVENT_SIM_IO_ERROR, slotIndex, -1)); } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(simStatus)) { sendMessage(obtainMessage(EVENT_SIM_RESTRICTED, slotIndex, -1)); } else if (IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(simStatus)) { // ICC_NOT_READY is a terminal state for an eSIM on the boot profile. At this // phase, the subscription list is accessible. // TODO(b/64216093): Clean up this special case, likely by treating NOT_READY // as equivalent to ABSENT, once the rest of the system can handle it. Currently // this breaks SystemUI which shows a "No SIM" icon. sendEmptyMessage(EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS); } else { logd("Ignoring simStatus: " + simStatus); } Loading Loading @@ -326,8 +333,7 @@ public class SubscriptionInfoUpdater extends Handler { break; case EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS: if (isAllIccIdQueryDone()) { updateEmbeddedSubscriptions(); if (updateEmbeddedSubscriptions()) { SubscriptionController.getInstance().notifySubscriptionInfoChanged(); } if (msg.obj != null) { Loading Loading @@ -659,26 +665,33 @@ public class SubscriptionInfoUpdater extends Handler { mSubscriptionManager.setDefaultDataSubId( mSubscriptionManager.getDefaultDataSubscriptionId()); // No need to check return value here as we notify for the above changes anyway. updateEmbeddedSubscriptions(); SubscriptionController.getInstance().notifySubscriptionInfoChanged(); logd("updateSubscriptionInfoByIccId:- SubscriptionInfo update complete"); } /** Update the cached list of embedded subscriptions. */ /** * Update the cached list of embedded subscriptions. * * @return true if changes may have been made. This is not a guarantee that changes were made, * but notifications about subscription changes may be skipped if this returns false as an * optimization to avoid spurious notifications. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void updateEmbeddedSubscriptions() { public boolean updateEmbeddedSubscriptions() { // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they // are filtered out of list calls as long as EuiccManager.isEnabled returns false). if (!mEuiccManager.isEnabled()) { return; return false; } GetEuiccProfileInfoListResult result = EuiccController.get().blockingGetEuiccProfileInfoList(); if (result == null) { // IPC to the eUICC controller failed. return; return false; } final EuiccProfileInfo[] embeddedProfiles; Loading @@ -698,6 +711,13 @@ public class SubscriptionInfoUpdater extends Handler { embeddedIccids[i] = embeddedProfiles[i].iccid; } // Note that this only tracks whether we make any writes to the DB. It's possible this will // be set to true for an update even when the row contents remain exactly unchanged from // before, since we don't compare against the previous value. Since this is only intended to // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this // is fine. boolean hasChanges = false; // Update or insert records for all embedded subscriptions (except non-removable ones if the // current eUICC is non-removable, since we assume these are still accessible though not // returned by the eUICC controller). Loading @@ -722,6 +742,7 @@ public class SubscriptionInfoUpdater extends Handler { values.put(SubscriptionManager.IS_REMOVABLE, isRemovable); values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.nickname); values.put(SubscriptionManager.NAME_SOURCE, SubscriptionManager.NAME_SOURCE_USER_INPUT); hasChanges = true; contentResolver.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.iccid + "\"", null); } Loading @@ -742,8 +763,11 @@ public class SubscriptionInfoUpdater extends Handler { + TextUtils.join(",", iccidsToRemove) + ")"; ContentValues values = new ContentValues(); values.put(SubscriptionManager.IS_EMBEDDED, 0); hasChanges = true; contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null); } return hasChanges; } private static int findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid) { Loading tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +31 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.telephony; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; Loading Loading @@ -503,7 +505,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[] { "1", "3"}, false /* removable */)).thenReturn(subInfoList); mUpdater.updateEmbeddedSubscriptions(); assertTrue(mUpdater.updateEmbeddedSubscriptions()); // 3 is new and so a new entry should have been created. verify(mSubscriptionController).insertEmptySubInfoRecord( Loading Loading @@ -554,7 +556,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[0], false /* removable */)).thenReturn(subInfoList); mUpdater.updateEmbeddedSubscriptions(); assertTrue(mUpdater.updateEmbeddedSubscriptions()); // No new entries should be created. verify(mSubscriptionController, times(0)).clearSubInfo(); Loading @@ -574,4 +576,31 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { assertEquals(0, iccid2Values.getValue().getAsInteger(SubscriptionManager.IS_EMBEDDED).intValue()); } @Test @SmallTest public void testUpdateEmbeddedSubscriptions_emptyToEmpty() throws Exception { when(mEuiccManager.isEnabled()).thenReturn(true); when(mEuiccController.blockingGetEuiccProfileInfoList()) .thenReturn(new GetEuiccProfileInfoListResult( 42, null /* subscriptions */, true /* removable */)); List<SubscriptionInfo> subInfoList = new ArrayList<>(); // 1: not embedded. subInfoList.add(new SubscriptionInfo( 0, "1", 0, "", "", 0, 0, "", 0, null, 0, 0, "", false /* isEmbedded */, null /* accessRules */)); when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[0], false /* removable */)).thenReturn(subInfoList); assertFalse(mUpdater.updateEmbeddedSubscriptions()); // No new entries should be created. verify(mSubscriptionController, never()).insertEmptySubInfoRecord(anyString(), anyInt()); // No existing entries should have been updated. verify(mContentProvider, never()).update(eq(SubscriptionManager.CONTENT_URI), any(), any(), isNull()); } } No newline at end of file Loading
src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java +30 −6 Original line number Diff line number Diff line Loading @@ -203,6 +203,13 @@ public class SubscriptionInfoUpdater extends Handler { sendMessage(obtainMessage(EVENT_SIM_IO_ERROR, slotIndex, -1)); } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(simStatus)) { sendMessage(obtainMessage(EVENT_SIM_RESTRICTED, slotIndex, -1)); } else if (IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(simStatus)) { // ICC_NOT_READY is a terminal state for an eSIM on the boot profile. At this // phase, the subscription list is accessible. // TODO(b/64216093): Clean up this special case, likely by treating NOT_READY // as equivalent to ABSENT, once the rest of the system can handle it. Currently // this breaks SystemUI which shows a "No SIM" icon. sendEmptyMessage(EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS); } else { logd("Ignoring simStatus: " + simStatus); } Loading Loading @@ -326,8 +333,7 @@ public class SubscriptionInfoUpdater extends Handler { break; case EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS: if (isAllIccIdQueryDone()) { updateEmbeddedSubscriptions(); if (updateEmbeddedSubscriptions()) { SubscriptionController.getInstance().notifySubscriptionInfoChanged(); } if (msg.obj != null) { Loading Loading @@ -659,26 +665,33 @@ public class SubscriptionInfoUpdater extends Handler { mSubscriptionManager.setDefaultDataSubId( mSubscriptionManager.getDefaultDataSubscriptionId()); // No need to check return value here as we notify for the above changes anyway. updateEmbeddedSubscriptions(); SubscriptionController.getInstance().notifySubscriptionInfoChanged(); logd("updateSubscriptionInfoByIccId:- SubscriptionInfo update complete"); } /** Update the cached list of embedded subscriptions. */ /** * Update the cached list of embedded subscriptions. * * @return true if changes may have been made. This is not a guarantee that changes were made, * but notifications about subscription changes may be skipped if this returns false as an * optimization to avoid spurious notifications. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) public void updateEmbeddedSubscriptions() { public boolean updateEmbeddedSubscriptions() { // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they // are filtered out of list calls as long as EuiccManager.isEnabled returns false). if (!mEuiccManager.isEnabled()) { return; return false; } GetEuiccProfileInfoListResult result = EuiccController.get().blockingGetEuiccProfileInfoList(); if (result == null) { // IPC to the eUICC controller failed. return; return false; } final EuiccProfileInfo[] embeddedProfiles; Loading @@ -698,6 +711,13 @@ public class SubscriptionInfoUpdater extends Handler { embeddedIccids[i] = embeddedProfiles[i].iccid; } // Note that this only tracks whether we make any writes to the DB. It's possible this will // be set to true for an update even when the row contents remain exactly unchanged from // before, since we don't compare against the previous value. Since this is only intended to // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this // is fine. boolean hasChanges = false; // Update or insert records for all embedded subscriptions (except non-removable ones if the // current eUICC is non-removable, since we assume these are still accessible though not // returned by the eUICC controller). Loading @@ -722,6 +742,7 @@ public class SubscriptionInfoUpdater extends Handler { values.put(SubscriptionManager.IS_REMOVABLE, isRemovable); values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.nickname); values.put(SubscriptionManager.NAME_SOURCE, SubscriptionManager.NAME_SOURCE_USER_INPUT); hasChanges = true; contentResolver.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.iccid + "\"", null); } Loading @@ -742,8 +763,11 @@ public class SubscriptionInfoUpdater extends Handler { + TextUtils.join(",", iccidsToRemove) + ")"; ContentValues values = new ContentValues(); values.put(SubscriptionManager.IS_EMBEDDED, 0); hasChanges = true; contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null); } return hasChanges; } private static int findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid) { Loading
tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java +31 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.telephony; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; Loading Loading @@ -503,7 +505,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[] { "1", "3"}, false /* removable */)).thenReturn(subInfoList); mUpdater.updateEmbeddedSubscriptions(); assertTrue(mUpdater.updateEmbeddedSubscriptions()); // 3 is new and so a new entry should have been created. verify(mSubscriptionController).insertEmptySubInfoRecord( Loading Loading @@ -554,7 +556,7 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[0], false /* removable */)).thenReturn(subInfoList); mUpdater.updateEmbeddedSubscriptions(); assertTrue(mUpdater.updateEmbeddedSubscriptions()); // No new entries should be created. verify(mSubscriptionController, times(0)).clearSubInfo(); Loading @@ -574,4 +576,31 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest { assertEquals(0, iccid2Values.getValue().getAsInteger(SubscriptionManager.IS_EMBEDDED).intValue()); } @Test @SmallTest public void testUpdateEmbeddedSubscriptions_emptyToEmpty() throws Exception { when(mEuiccManager.isEnabled()).thenReturn(true); when(mEuiccController.blockingGetEuiccProfileInfoList()) .thenReturn(new GetEuiccProfileInfoListResult( 42, null /* subscriptions */, true /* removable */)); List<SubscriptionInfo> subInfoList = new ArrayList<>(); // 1: not embedded. subInfoList.add(new SubscriptionInfo( 0, "1", 0, "", "", 0, 0, "", 0, null, 0, 0, "", false /* isEmbedded */, null /* accessRules */)); when(mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( new String[0], false /* removable */)).thenReturn(subInfoList); assertFalse(mUpdater.updateEmbeddedSubscriptions()); // No new entries should be created. verify(mSubscriptionController, never()).insertEmptySubInfoRecord(anyString(), anyInt()); // No existing entries should have been updated. verify(mContentProvider, never()).update(eq(SubscriptionManager.CONTENT_URI), any(), any(), isNull()); } } No newline at end of file