Loading src/java/com/android/internal/telephony/MultiSimSettingController.java +4 −17 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELE import android.content.Context; import android.content.Intent; import android.os.ParcelUuid; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.telephony.SubscriptionInfo; Loading Loading @@ -299,7 +300,7 @@ public class MultiSimSettingController { private synchronized void setUserDataEnabledForGroup(int subId, boolean enable) { log("setUserDataEnabledForGroup subId " + subId + " enable " + enable); List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( subId, mContext.getOpPackageName()); mSubController.getGroupUuid(subId), mContext.getOpPackageName()); if (infoList == null) return; Loading Loading @@ -339,7 +340,7 @@ public class MultiSimSettingController { private synchronized void setRoamingDataEnabledForGroup(int subId, boolean enable) { SubscriptionController subController = SubscriptionController.getInstance(); List<SubscriptionInfo> infoList = subController.getSubscriptionsInGroup( subId, mContext.getOpPackageName()); mSubController.getGroupUuid(subId), mContext.getOpPackageName()); if (infoList == null) return; Loading @@ -350,20 +351,6 @@ public class MultiSimSettingController { } } private String getGroupUuid(int subId) { String groupUuid; List<SubscriptionInfo> subInfo = mSubController.getSubInfo( SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null); if (subInfo == null || subInfo.size() == 0) { groupUuid = null; } else { groupUuid = subInfo.get(0).getGroupUuid(); } return groupUuid; } private interface UpdateDefaultAction { void update(int newValue); } Loading @@ -375,7 +362,7 @@ public class MultiSimSettingController { if (subInfos.size() > 0) { // Get groupUuid of old String groupUuid = getGroupUuid(oldValue); ParcelUuid groupUuid = mSubController.getGroupUuid(oldValue); for (SubscriptionInfo info : subInfos) { int id = info.getSubscriptionId(); Loading src/java/com/android/internal/telephony/SubscriptionController.java +61 −40 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Binder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; Loading Loading @@ -1638,7 +1639,7 @@ public class SubscriptionController extends ISub.Stub { } private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { List<SubscriptionInfo> infoList = getSubscriptionsInGroup(subId, List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), mContext.getOpPackageName()); if (!updateEntireGroup || infoList == null || infoList.size() == 0) { // Only update specified subscriptions. Loading Loading @@ -2711,7 +2712,7 @@ public class SubscriptionController extends ISub.Stub { * */ @Override public String setSubscriptionGroup(int[] subIdList, String callingPackage) { public ParcelUuid createSubscriptionGroup(int[] subIdList, String callingPackage) { if (subIdList == null || subIdList.length == 0) { return null; } Loading @@ -2728,14 +2729,14 @@ public class SubscriptionController extends ISub.Stub { try { // Generate a UUID. String groupUUID = UUID.randomUUID().toString(); ParcelUuid groupUUID = new ParcelUuid(UUID.randomUUID()); ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, groupUUID); value.put(SubscriptionManager.GROUP_UUID, groupUUID.toString()); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("setSubscriptionGroup update DB result: " + result); if (DBG) logdl("createSubscriptionGroup update DB result: " + result); refreshCachedActiveSubscriptionInfoList(); Loading @@ -2749,25 +2750,33 @@ public class SubscriptionController extends ISub.Stub { } } @Override public void addSubscriptionsIntoGroup(int[] subIdList, ParcelUuid groupUuid, String callingPackage) { // TODO: implement it. } /** * Remove a list of subscriptions from their subscription group. * See {@link #setSubscriptionGroup(int[], String)} for more details. * See {@link SubscriptionManager#createSubscriptionGroup(List<Integer>)} for more details. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: * {@link TelephonyManager#hasCarrierPrivileges(int)} or * {@link TelephonyManager#hasCarrierPrivileges()} or * {@link SubscriptionManager#canManageSubscription(SubscriptionInfo)} * * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong * the specified group. * * @param subIdList list of subId that need removing from their groups. * @return whether the operation succeeds. * */ public boolean removeSubscriptionsFromGroup(int[] subIdList, String callingPackage) { public void removeSubscriptionsFromGroup(int[] subIdList, ParcelUuid groupUuid, String callingPackage) { if (subIdList == null || subIdList.length == 0) { return false; return; } // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. If it's due to invalid parameter or internal state, Loading @@ -2775,24 +2784,30 @@ public class SubscriptionController extends ISub.Stub { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) != PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList( subIdList, callingPackage)) { return false; return; } long identity = Binder.clearCallingIdentity(); try { List<SubscriptionInfo> subInfoList = getSubInfo(getSelectionForSubIdList(subIdList), null); for (SubscriptionInfo info : subInfoList) { if (!groupUuid.equals(info.getGroupUuid())) { throw new IllegalArgumentException("Subscription " + info.getSubscriptionId() + " doesn't belong to group " + groupUuid); } } ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, (String) null); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("setSubscriptionGroup update DB result: " + result); if (DBG) logdl("removeSubscriptionsFromGroup update DB result: " + result); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); return result != 0; } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -2877,7 +2892,7 @@ public class SubscriptionController extends ISub.Stub { /** * Get subscriptionInfo list of subscriptions that are in the same group of given subId. * See {@link #setSubscriptionGroup(int[], String)} for more details. * See {@link #createSubscriptionGroup(int[], String)} for more details. * * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} * permission or had carrier privilege permission on the subscription. Loading @@ -2886,40 +2901,46 @@ public class SubscriptionController extends ISub.Stub { * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * * @param subId of which list of subInfo from the same group will be returned. * @param groupUuid of which list of subInfo will be returned. * @return list of subscriptionInfo that belong to the same group, including the given * subscription itself. It will return null if the subscription doesn't exist or it * doesn't belong to any group. * subscription itself. It will return an empty list if no subscription belongs to the group. * */ public List<SubscriptionInfo> getSubscriptionsInGroup(int subId, String callingPackage) { if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, subId, callingPackage, "getSubscriptionsInGroup")) { return null; } @Override public List<SubscriptionInfo> getSubscriptionsInGroup(ParcelUuid groupUuid, String callingPackage) { long identity = Binder.clearCallingIdentity(); List<SubscriptionInfo> subInfoList; try { SubscriptionInfo info = getActiveSubscriptionInfo(subId, callingPackage); if (info == null || TextUtils.isEmpty(info.getGroupUuid())) { return null; } String groupUuid = info.getGroupUuid(); List<SubscriptionInfo> infoList = getAvailableSubscriptionInfoList(callingPackage); // Shouldn't happen because we've verified the subId belongs to an active subscription. if (infoList == null) { return null; subInfoList = getAllSubInfoList(mContext.getOpPackageName()); if (groupUuid == null || subInfoList == null || subInfoList.isEmpty()) { return new ArrayList<>(); } return infoList.stream().filter( subscriptionInfo -> groupUuid.equals(subscriptionInfo.getGroupUuid())) .collect(Collectors.toList()); } finally { Binder.restoreCallingIdentity(identity); } return subInfoList.stream().filter(info -> { if (!groupUuid.equals(info.getGroupUuid())) return false; int subId = info.getSubscriptionId(); return TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage, "getSubscriptionsInGroup") || (info.isEmbedded() && info.canManageSubscription(mContext, callingPackage)); }).collect(Collectors.toList()); } public ParcelUuid getGroupUuid(int subId) { ParcelUuid groupUuid; List<SubscriptionInfo> subInfo = getSubInfo(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null); if (subInfo == null || subInfo.size() == 0) { groupUuid = null; } else { groupUuid = subInfo.get(0).getGroupUuid(); } return groupUuid; } @Override Loading Loading @@ -3288,7 +3309,7 @@ public class SubscriptionController extends ISub.Stub { } } private boolean shouldDisableSubGroup(String groupUuid) { private boolean shouldDisableSubGroup(ParcelUuid groupUuid) { if (groupUuid == null) return false; for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) { Loading tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java +12 −7 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.ParcelUuid; import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; Loading @@ -43,6 +44,7 @@ import org.mockito.Mock; import java.util.Arrays; import java.util.List; import java.util.UUID; public class MultiSimSettingControllerTest extends TelephonyTest { private static final int SINGLE_SIM = 1; Loading @@ -60,25 +62,27 @@ public class MultiSimSettingControllerTest extends TelephonyTest { private DataEnabledSettings mDataEnabledSettingsMock2; private Phone[] mPhones; ParcelUuid mGroupUuid1 = new ParcelUuid(UUID.randomUUID()); private SubscriptionInfo mSubInfo1 = new SubscriptionInfo(1, "subInfo1 IccId", 0, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null); private SubscriptionInfo mSubInfo2 = new SubscriptionInfo(2, "subInfo2 IccId", 1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); private SubscriptionInfo mSubInfo3 = new SubscriptionInfo(3, "subInfo3 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); private SubscriptionInfo mSubInfo4 = new SubscriptionInfo(4, "subInfo4 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); Loading Loading @@ -171,7 +175,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { // Create subscription grouping. doReturn(Arrays.asList(mSubInfo2, mSubInfo3, mSubInfo4)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(2), anyString()); .getSubscriptionsInGroup(any(), anyString()); mMultiSimSettingControllerUT.onSubscriptionGroupCreated(new int[] {2, 3, 4}); // This should result in setting sync. assertTrue(GlobalSettingsHelper.getBoolean( Loading Loading @@ -201,6 +205,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { doReturn(2).when(mSubControllerMock).getDefaultSmsSubId(); doReturn(1).when(mSubControllerMock).getDefaultVoiceSubId(); List<SubscriptionInfo> infoList = Arrays.asList(mSubInfo1, mSubInfo3); doReturn(mGroupUuid1).when(mSubControllerMock).getGroupUuid(2); doReturn(infoList).when(mSubControllerMock).getActiveSubscriptionInfoList(anyString()); mMultiSimSettingControllerUT.updateDefaults(); verify(mSubControllerMock).setDefaultDataSubId(3); Loading Loading @@ -243,7 +248,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { public void testGroupedCbrs() throws Exception { // Mark sub 1 as opportunistic. replaceInstance(SubscriptionInfo.class, "mIsOpportunistic", mSubInfo1, true); replaceInstance(SubscriptionInfo.class, "mGroupUUID", mSubInfo1, "group1"); replaceInstance(SubscriptionInfo.class, "mGroupUUID", mSubInfo1, mGroupUuid1); doReturn(true).when(mSubControllerMock).isOpportunistic(1); // Make opportunistic sub 1 and sub 2 data enabled. doReturn(true).when(mPhoneMock1).isUserDataEnabled(); Loading @@ -259,9 +264,9 @@ public class MultiSimSettingControllerTest extends TelephonyTest { GlobalSettingsHelper.setBoolean(mContext, Settings.Global.MOBILE_DATA, 2, false); // Group sub 1 with sub 2. doReturn(Arrays.asList(mSubInfo1, mSubInfo2)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(1), anyString()); .getSubscriptionsInGroup(any(), anyString()); doReturn(Arrays.asList(mSubInfo1, mSubInfo2)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(2), anyString()); .getSubscriptionsInGroup(any(), anyString()); mMultiSimSettingControllerUT.onSubscriptionGroupCreated(new int[] {1, 2}); // This should result in setting sync. verify(mDataEnabledSettingsMock1).setUserDataEnabled(false); Loading tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java +23 −18 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.Manifest; import android.content.ContentValues; import android.content.Intent; import android.os.Bundle; import android.os.ParcelUuid; import android.os.UserHandle; import android.provider.Settings; import android.telephony.SubscriptionInfo; Loading Loading @@ -584,21 +585,21 @@ public class SubscriptionControllerTest extends TelephonyTest { int[] subIdList = new int[] {1, 2}; try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission."); fail("createSubscriptionGroup should fail with no permission."); } catch (SecurityException e) { // Expected result. } // With modify permission it should succeed. mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE); String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); // Calling it again should generate a new group ID. String newGroupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, newGroupId); assertNotEquals(groupId, newGroupId); Loading @@ -623,24 +624,24 @@ public class SubscriptionControllerTest extends TelephonyTest { int[] subIdList = new int[] {1, 2}; // It should fail since it has no permission. try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission."); fail("createSubscriptionGroup should fail with no permission."); } catch (SecurityException e) { // Expected result. } doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission on sub 2."); fail("createSubscriptionGroup should fail with no permission on sub 2."); } catch (SecurityException e) { // Expected result. } doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); Loading @@ -658,7 +659,7 @@ public class SubscriptionControllerTest extends TelephonyTest { doReturn(true).when(mSubscriptionManager).canManageSubscription( eq(subInfoList.get(1)), anyString()); String newGroupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, newGroupId); assertNotEquals(groupId, newGroupId); Loading @@ -685,7 +686,7 @@ public class SubscriptionControllerTest extends TelephonyTest { // Set sub 1 and 2 into same group. int[] subIdList = new int[] {1, 2}; String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); Loading Loading @@ -717,21 +718,26 @@ public class SubscriptionControllerTest extends TelephonyTest { public void testSetSubscriptionGroup() throws Exception { testInsertSim(); // Adding a second profile and mark as embedded. mSubscriptionControllerUT.addSubInfoRecord("test2", 0); mSubscriptionControllerUT.addSubInfoRecord("test2", 1); ContentValues values = new ContentValues(); values.put(SubscriptionManager.IS_EMBEDDED, 1); mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); assertTrue(mSubscriptionControllerUT.isActiveSubId(1)); assertTrue(mSubscriptionControllerUT.isActiveSubId(2)); assertTrue(TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, 1, mContext.getOpPackageName(), "getSubscriptionsInGroup")); int[] subIdList = new int[] {1, 2}; String groupUuid = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupUuid); // Sub 1 and sub 2 should be in same group. List<SubscriptionInfo> infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(1, mContext.getOpPackageName()); .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertNotEquals(null, infoList); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); Loading @@ -739,11 +745,10 @@ public class SubscriptionControllerTest extends TelephonyTest { // Remove group of sub 1. subIdList = new int[] {1}; boolean result = mSubscriptionControllerUT.removeSubscriptionsFromGroup( subIdList, mContext.getOpPackageName()); assertEquals(true, result); mSubscriptionControllerUT.removeSubscriptionsFromGroup( subIdList, groupUuid, mContext.getOpPackageName()); infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(2, mContext.getOpPackageName()); .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertEquals(1, infoList.size()); assertEquals(2, infoList.get(0).getSubscriptionId()); } Loading tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -980,7 +980,7 @@ public class EuiccControllerTest extends TelephonyTest { SubscriptionInfo subInfo = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID, false, "", false, 0, 0, 0); false, null, false, 0, 0, 0); when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn( hasPrivileges); when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn( Loading @@ -1001,11 +1001,11 @@ public class EuiccControllerTest extends TelephonyTest { SubscriptionInfo subInfo1 = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID, false, "", false, 0, 0, 0); false, null, false, 0, 0, 0); SubscriptionInfo subInfo2 = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", 1 /* cardId */, false, "", false, 0, 0, 0); 1 /* cardId */, false, null, false, 0, 0, 0); when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn( hasPrivileges); when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn( Loading Loading
src/java/com/android/internal/telephony/MultiSimSettingController.java +4 −17 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELE import android.content.Context; import android.content.Intent; import android.os.ParcelUuid; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.telephony.SubscriptionInfo; Loading Loading @@ -299,7 +300,7 @@ public class MultiSimSettingController { private synchronized void setUserDataEnabledForGroup(int subId, boolean enable) { log("setUserDataEnabledForGroup subId " + subId + " enable " + enable); List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( subId, mContext.getOpPackageName()); mSubController.getGroupUuid(subId), mContext.getOpPackageName()); if (infoList == null) return; Loading Loading @@ -339,7 +340,7 @@ public class MultiSimSettingController { private synchronized void setRoamingDataEnabledForGroup(int subId, boolean enable) { SubscriptionController subController = SubscriptionController.getInstance(); List<SubscriptionInfo> infoList = subController.getSubscriptionsInGroup( subId, mContext.getOpPackageName()); mSubController.getGroupUuid(subId), mContext.getOpPackageName()); if (infoList == null) return; Loading @@ -350,20 +351,6 @@ public class MultiSimSettingController { } } private String getGroupUuid(int subId) { String groupUuid; List<SubscriptionInfo> subInfo = mSubController.getSubInfo( SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null); if (subInfo == null || subInfo.size() == 0) { groupUuid = null; } else { groupUuid = subInfo.get(0).getGroupUuid(); } return groupUuid; } private interface UpdateDefaultAction { void update(int newValue); } Loading @@ -375,7 +362,7 @@ public class MultiSimSettingController { if (subInfos.size() > 0) { // Get groupUuid of old String groupUuid = getGroupUuid(oldValue); ParcelUuid groupUuid = mSubController.getGroupUuid(oldValue); for (SubscriptionInfo info : subInfos) { int id = info.getSubscriptionId(); Loading
src/java/com/android/internal/telephony/SubscriptionController.java +61 −40 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Binder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; Loading Loading @@ -1638,7 +1639,7 @@ public class SubscriptionController extends ISub.Stub { } private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { List<SubscriptionInfo> infoList = getSubscriptionsInGroup(subId, List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), mContext.getOpPackageName()); if (!updateEntireGroup || infoList == null || infoList.size() == 0) { // Only update specified subscriptions. Loading Loading @@ -2711,7 +2712,7 @@ public class SubscriptionController extends ISub.Stub { * */ @Override public String setSubscriptionGroup(int[] subIdList, String callingPackage) { public ParcelUuid createSubscriptionGroup(int[] subIdList, String callingPackage) { if (subIdList == null || subIdList.length == 0) { return null; } Loading @@ -2728,14 +2729,14 @@ public class SubscriptionController extends ISub.Stub { try { // Generate a UUID. String groupUUID = UUID.randomUUID().toString(); ParcelUuid groupUUID = new ParcelUuid(UUID.randomUUID()); ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, groupUUID); value.put(SubscriptionManager.GROUP_UUID, groupUUID.toString()); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("setSubscriptionGroup update DB result: " + result); if (DBG) logdl("createSubscriptionGroup update DB result: " + result); refreshCachedActiveSubscriptionInfoList(); Loading @@ -2749,25 +2750,33 @@ public class SubscriptionController extends ISub.Stub { } } @Override public void addSubscriptionsIntoGroup(int[] subIdList, ParcelUuid groupUuid, String callingPackage) { // TODO: implement it. } /** * Remove a list of subscriptions from their subscription group. * See {@link #setSubscriptionGroup(int[], String)} for more details. * See {@link SubscriptionManager#createSubscriptionGroup(List<Integer>)} for more details. * * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} * permission or had carrier privilege permission on the subscriptions: * {@link TelephonyManager#hasCarrierPrivileges(int)} or * {@link TelephonyManager#hasCarrierPrivileges()} or * {@link SubscriptionManager#canManageSubscription(SubscriptionInfo)} * * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong * the specified group. * * @param subIdList list of subId that need removing from their groups. * @return whether the operation succeeds. * */ public boolean removeSubscriptionsFromGroup(int[] subIdList, String callingPackage) { public void removeSubscriptionsFromGroup(int[] subIdList, ParcelUuid groupUuid, String callingPackage) { if (subIdList == null || subIdList.length == 0) { return false; return; } // If it doesn't have modify phone state permission, or carrier privilege permission, // a SecurityException will be thrown. If it's due to invalid parameter or internal state, Loading @@ -2775,24 +2784,30 @@ public class SubscriptionController extends ISub.Stub { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) != PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList( subIdList, callingPackage)) { return false; return; } long identity = Binder.clearCallingIdentity(); try { List<SubscriptionInfo> subInfoList = getSubInfo(getSelectionForSubIdList(subIdList), null); for (SubscriptionInfo info : subInfoList) { if (!groupUuid.equals(info.getGroupUuid())) { throw new IllegalArgumentException("Subscription " + info.getSubscriptionId() + " doesn't belong to group " + groupUuid); } } ContentValues value = new ContentValues(); value.put(SubscriptionManager.GROUP_UUID, (String) null); int result = mContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, getSelectionForSubIdList(subIdList), null); if (DBG) logdl("setSubscriptionGroup update DB result: " + result); if (DBG) logdl("removeSubscriptionsFromGroup update DB result: " + result); refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); return result != 0; } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -2877,7 +2892,7 @@ public class SubscriptionController extends ISub.Stub { /** * Get subscriptionInfo list of subscriptions that are in the same group of given subId. * See {@link #setSubscriptionGroup(int[], String)} for more details. * See {@link #createSubscriptionGroup(int[], String)} for more details. * * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} * permission or had carrier privilege permission on the subscription. Loading @@ -2886,40 +2901,46 @@ public class SubscriptionController extends ISub.Stub { * @throws SecurityException if the caller doesn't meet the requirements * outlined above. * * @param subId of which list of subInfo from the same group will be returned. * @param groupUuid of which list of subInfo will be returned. * @return list of subscriptionInfo that belong to the same group, including the given * subscription itself. It will return null if the subscription doesn't exist or it * doesn't belong to any group. * subscription itself. It will return an empty list if no subscription belongs to the group. * */ public List<SubscriptionInfo> getSubscriptionsInGroup(int subId, String callingPackage) { if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState( mContext, subId, callingPackage, "getSubscriptionsInGroup")) { return null; } @Override public List<SubscriptionInfo> getSubscriptionsInGroup(ParcelUuid groupUuid, String callingPackage) { long identity = Binder.clearCallingIdentity(); List<SubscriptionInfo> subInfoList; try { SubscriptionInfo info = getActiveSubscriptionInfo(subId, callingPackage); if (info == null || TextUtils.isEmpty(info.getGroupUuid())) { return null; } String groupUuid = info.getGroupUuid(); List<SubscriptionInfo> infoList = getAvailableSubscriptionInfoList(callingPackage); // Shouldn't happen because we've verified the subId belongs to an active subscription. if (infoList == null) { return null; subInfoList = getAllSubInfoList(mContext.getOpPackageName()); if (groupUuid == null || subInfoList == null || subInfoList.isEmpty()) { return new ArrayList<>(); } return infoList.stream().filter( subscriptionInfo -> groupUuid.equals(subscriptionInfo.getGroupUuid())) .collect(Collectors.toList()); } finally { Binder.restoreCallingIdentity(identity); } return subInfoList.stream().filter(info -> { if (!groupUuid.equals(info.getGroupUuid())) return false; int subId = info.getSubscriptionId(); return TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage, "getSubscriptionsInGroup") || (info.isEmbedded() && info.canManageSubscription(mContext, callingPackage)); }).collect(Collectors.toList()); } public ParcelUuid getGroupUuid(int subId) { ParcelUuid groupUuid; List<SubscriptionInfo> subInfo = getSubInfo(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null); if (subInfo == null || subInfo.size() == 0) { groupUuid = null; } else { groupUuid = subInfo.get(0).getGroupUuid(); } return groupUuid; } @Override Loading Loading @@ -3288,7 +3309,7 @@ public class SubscriptionController extends ISub.Stub { } } private boolean shouldDisableSubGroup(String groupUuid) { private boolean shouldDisableSubGroup(ParcelUuid groupUuid) { if (groupUuid == null) return false; for (SubscriptionInfo activeInfo : mCacheActiveSubInfoList) { Loading
tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java +12 −7 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.ParcelUuid; import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; Loading @@ -43,6 +44,7 @@ import org.mockito.Mock; import java.util.Arrays; import java.util.List; import java.util.UUID; public class MultiSimSettingControllerTest extends TelephonyTest { private static final int SINGLE_SIM = 1; Loading @@ -60,25 +62,27 @@ public class MultiSimSettingControllerTest extends TelephonyTest { private DataEnabledSettings mDataEnabledSettingsMock2; private Phone[] mPhones; ParcelUuid mGroupUuid1 = new ParcelUuid(UUID.randomUUID()); private SubscriptionInfo mSubInfo1 = new SubscriptionInfo(1, "subInfo1 IccId", 0, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null); private SubscriptionInfo mSubInfo2 = new SubscriptionInfo(2, "subInfo2 IccId", 1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); private SubscriptionInfo mSubInfo3 = new SubscriptionInfo(3, "subInfo3 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); private SubscriptionInfo mSubInfo4 = new SubscriptionInfo(4, "subInfo4 IccId", -1, "T-mobile", "T-mobile", 0, 255, "12345", 0, null, "310", "260", "156", false, null, null, -1, false, "group1", false, "156", false, null, null, -1, false, mGroupUuid1.toString(), false, TelephonyManager.UNKNOWN_CARRIER_ID, SubscriptionManager.PROFILE_CLASS_DEFAULT, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); Loading Loading @@ -171,7 +175,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { // Create subscription grouping. doReturn(Arrays.asList(mSubInfo2, mSubInfo3, mSubInfo4)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(2), anyString()); .getSubscriptionsInGroup(any(), anyString()); mMultiSimSettingControllerUT.onSubscriptionGroupCreated(new int[] {2, 3, 4}); // This should result in setting sync. assertTrue(GlobalSettingsHelper.getBoolean( Loading Loading @@ -201,6 +205,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { doReturn(2).when(mSubControllerMock).getDefaultSmsSubId(); doReturn(1).when(mSubControllerMock).getDefaultVoiceSubId(); List<SubscriptionInfo> infoList = Arrays.asList(mSubInfo1, mSubInfo3); doReturn(mGroupUuid1).when(mSubControllerMock).getGroupUuid(2); doReturn(infoList).when(mSubControllerMock).getActiveSubscriptionInfoList(anyString()); mMultiSimSettingControllerUT.updateDefaults(); verify(mSubControllerMock).setDefaultDataSubId(3); Loading Loading @@ -243,7 +248,7 @@ public class MultiSimSettingControllerTest extends TelephonyTest { public void testGroupedCbrs() throws Exception { // Mark sub 1 as opportunistic. replaceInstance(SubscriptionInfo.class, "mIsOpportunistic", mSubInfo1, true); replaceInstance(SubscriptionInfo.class, "mGroupUUID", mSubInfo1, "group1"); replaceInstance(SubscriptionInfo.class, "mGroupUUID", mSubInfo1, mGroupUuid1); doReturn(true).when(mSubControllerMock).isOpportunistic(1); // Make opportunistic sub 1 and sub 2 data enabled. doReturn(true).when(mPhoneMock1).isUserDataEnabled(); Loading @@ -259,9 +264,9 @@ public class MultiSimSettingControllerTest extends TelephonyTest { GlobalSettingsHelper.setBoolean(mContext, Settings.Global.MOBILE_DATA, 2, false); // Group sub 1 with sub 2. doReturn(Arrays.asList(mSubInfo1, mSubInfo2)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(1), anyString()); .getSubscriptionsInGroup(any(), anyString()); doReturn(Arrays.asList(mSubInfo1, mSubInfo2)).when(mSubControllerMock) .getSubscriptionsInGroup(eq(2), anyString()); .getSubscriptionsInGroup(any(), anyString()); mMultiSimSettingControllerUT.onSubscriptionGroupCreated(new int[] {1, 2}); // This should result in setting sync. verify(mDataEnabledSettingsMock1).setUserDataEnabled(false); Loading
tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java +23 −18 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.Manifest; import android.content.ContentValues; import android.content.Intent; import android.os.Bundle; import android.os.ParcelUuid; import android.os.UserHandle; import android.provider.Settings; import android.telephony.SubscriptionInfo; Loading Loading @@ -584,21 +585,21 @@ public class SubscriptionControllerTest extends TelephonyTest { int[] subIdList = new int[] {1, 2}; try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission."); fail("createSubscriptionGroup should fail with no permission."); } catch (SecurityException e) { // Expected result. } // With modify permission it should succeed. mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE); String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); // Calling it again should generate a new group ID. String newGroupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, newGroupId); assertNotEquals(groupId, newGroupId); Loading @@ -623,24 +624,24 @@ public class SubscriptionControllerTest extends TelephonyTest { int[] subIdList = new int[] {1, 2}; // It should fail since it has no permission. try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission."); fail("createSubscriptionGroup should fail with no permission."); } catch (SecurityException e) { // Expected result. } doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(1); try { mSubscriptionControllerUT.setSubscriptionGroup( mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); fail("setSubscriptionGroup should fail with no permission on sub 2."); fail("createSubscriptionGroup should fail with no permission on sub 2."); } catch (SecurityException e) { // Expected result. } doReturn(true).when(mTelephonyManager).hasCarrierPrivileges(2); String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); Loading @@ -658,7 +659,7 @@ public class SubscriptionControllerTest extends TelephonyTest { doReturn(true).when(mSubscriptionManager).canManageSubscription( eq(subInfoList.get(1)), anyString()); String newGroupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid newGroupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, newGroupId); assertNotEquals(groupId, newGroupId); Loading @@ -685,7 +686,7 @@ public class SubscriptionControllerTest extends TelephonyTest { // Set sub 1 and 2 into same group. int[] subIdList = new int[] {1, 2}; String groupId = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupId = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupId); Loading Loading @@ -717,21 +718,26 @@ public class SubscriptionControllerTest extends TelephonyTest { public void testSetSubscriptionGroup() throws Exception { testInsertSim(); // Adding a second profile and mark as embedded. mSubscriptionControllerUT.addSubInfoRecord("test2", 0); mSubscriptionControllerUT.addSubInfoRecord("test2", 1); ContentValues values = new ContentValues(); values.put(SubscriptionManager.IS_EMBEDDED, 1); mFakeTelephonyProvider.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "=" + 2, null); mSubscriptionControllerUT.refreshCachedActiveSubscriptionInfoList(); assertTrue(mSubscriptionControllerUT.isActiveSubId(1)); assertTrue(mSubscriptionControllerUT.isActiveSubId(2)); assertTrue(TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, 1, mContext.getOpPackageName(), "getSubscriptionsInGroup")); int[] subIdList = new int[] {1, 2}; String groupUuid = mSubscriptionControllerUT.setSubscriptionGroup( ParcelUuid groupUuid = mSubscriptionControllerUT.createSubscriptionGroup( subIdList, mContext.getOpPackageName()); assertNotEquals(null, groupUuid); // Sub 1 and sub 2 should be in same group. List<SubscriptionInfo> infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(1, mContext.getOpPackageName()); .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertNotEquals(null, infoList); assertEquals(2, infoList.size()); assertEquals(1, infoList.get(0).getSubscriptionId()); Loading @@ -739,11 +745,10 @@ public class SubscriptionControllerTest extends TelephonyTest { // Remove group of sub 1. subIdList = new int[] {1}; boolean result = mSubscriptionControllerUT.removeSubscriptionsFromGroup( subIdList, mContext.getOpPackageName()); assertEquals(true, result); mSubscriptionControllerUT.removeSubscriptionsFromGroup( subIdList, groupUuid, mContext.getOpPackageName()); infoList = mSubscriptionControllerUT .getSubscriptionsInGroup(2, mContext.getOpPackageName()); .getSubscriptionsInGroup(groupUuid, mContext.getOpPackageName()); assertEquals(1, infoList.size()); assertEquals(2, infoList.get(0).getSubscriptionId()); } Loading
tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -980,7 +980,7 @@ public class EuiccControllerTest extends TelephonyTest { SubscriptionInfo subInfo = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID, false, "", false, 0, 0, 0); false, null, false, 0, 0, 0); when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn( hasPrivileges); when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn( Loading @@ -1001,11 +1001,11 @@ public class EuiccControllerTest extends TelephonyTest { SubscriptionInfo subInfo1 = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", CARD_ID, false, "", false, 0, 0, 0); false, null, false, 0, 0, 0); SubscriptionInfo subInfo2 = new SubscriptionInfo( 0, "", 0, "", "", 0, 0, "", 0, null, "", "", "", true /* isEmbedded */, hasPrivileges ? new UiccAccessRule[] { ACCESS_RULE } : null, "", 1 /* cardId */, false, "", false, 0, 0, 0); 1 /* cardId */, false, null, false, 0, 0, 0); when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn( hasPrivileges); when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn( Loading